들어가기에 앞서
실제 프로젝트 진행했던 코드 내용 및 세부 내용은 일부만 업로드하였습니다.
Spring Boot
의 slice test를 사용하지 않는 방법으로 테스트 진행 예정SpringBootApplication
을 띄우지 않고 가볍게 테스트 할 수 있게mockito
사용import com.fastcampus.projectboard.domain.type.SearchType;
import com.fastcampus.projectboard.dto.ArticleDto;
import com.fastcampus.projectboard.repository.ArticleRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@RequiredArgsConstructor
@Transactional
@Service
public class ArticleService {
private final ArticleRepository articleRepository;
import com.fastcampus.projectboard.domain.type.SearchType;
import com.fastcampus.projectboard.dto.ArticleDto;
import com.fastcampus.projectboard.repository.ArticleRepository;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
@DisplayName("비즈니스 로직 - 게시글")
@ExtendWith(MockitoExtension.class)
class ArticleServiceTest {
@InjectMocks private ArticleService sut; // Mock을 주입해주는 대상에만 @InjectMocks
@Mock private ArticleRepository articleRepository; // InjectMocks 외의 모든 대상
@DisplayName("게시글 검색 시 게시글 페이지를 반환")
// 게시글 검색 시 게시글 리스트, 게시글 페이지네이션, 정렬 기능 모두 구현됨 (Page)
@Test
void givenSearchParameters_whenSearchingArticles_thenReturnsArticleList() {
// Given
// When
Page<ArticleDto> articles = sut.searchArticles(SearchType.TITLE, "search keyword"); // 제목, 본문, ID, 닉네임, 해시태그
// Then
assertThat(articles).isNotNull();
}
import java.io.Serializable;
import java.time.LocalDateTime;
public record ArticleDto(
LocalDateTime createdAt,
String createdBy,
String title,
String content,
String hashtag
) implements Serializable {
public static ArticleDto of(LocalDateTime createdAt, String createdBy, String title, String content, String hashtag) {
return new ArticleDto(createdAt, createdBy, title, content, hashtag);
}
}
public enum SearchType {
TITLE, CONTENT, ID, NICKNAME, HASHTAG
}
@Transactional(readOnly = true)
public Page<ArticleDto> searchArticles(SearchType title, String search_keyword) {
return Page.empty(); // 아직 실제 페이지가 구현되지 않아 null 처리
}
@DisplayName("게시글 조회 시 게시글을 반환")
@Test
void givenArticleId_whenSearchingArticle_thenReturnsArticle() {
// Given
// When
ArticleDto article = sut.searchArticle(1L); // 제목, 본문, ID, 닉네임, 해시태그
// Then
assertThat(article).isNotNull();
}
@Transactional(readOnly = true)
public ArticleDto searchArticle(long l) {
return null; // 아직 실제 페이지가 구현되지 않아 null 처리
}
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class MainController {
@GetMapping("/")
public String root() {
return "redirect:/articles";
}
import com.fastcampus.projectboard.config.SecurityConfig;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.context.annotation.Import;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@DisplayName("View 컨트롤러 - 리다이렉션")
@Import(SecurityConfig.class)
@WebMvcTest(MainController.class)
class MainControllerTest {
private final MockMvc mvc;
public MainControllerTest(@Autowired MockMvc mvc) {
this.mvc = mvc;
}
@DisplayName("[VIEW][GET] 루트 페이지 -> 게시판 페이지로 리다이렉션")
@Test
void givenNothing_whenRequestingRootPage_thenRedirectsToArticlePage() throws Exception {
// Given
// When & Then
mvc.perform(get("/"))
.andExpect(status().is3xxRedirection());
}
}