테스트코드 부족한 부분 생각
검색 기능 테스트 코드 구현 중
@ExtendWith(MockitoExtension.class)를 사용하는 경우와
MockitoAnnotations.initMocks(this)를 + @BeforeEach 메서드를 사용하는 경우
간단하게 검색의 성공과 실패에 대한 테스트 코드를 작성해보았다.
class SearchServiceTest {
@Mock
private MenuRepository menuRepository;
@Mock
private StoreRepository storeRepository;
@InjectMocks
private SearchService searchService;
@BeforeEach
void setUp() {
MockitoAnnotations.initMocks(this);
}
@Test
@DisplayName("메뉴와 가게 이름으로 검색 성공")
public void testSearchStoresAndMenusByKeyword_Success() {
// given
String keyword = "1";
List<Menu> mockMenus = new ArrayList<>();
List<Store> mockStores = new ArrayList<>();
// 가짜 메뉴와 가게 데이터를 생성하고 Mock 설정
Menu menu1 = new Menu();
menu1.setMenuName("Menu 1");
Store store1 = new Store();
store1.setId(1L);
store1.setStoreName("Store 1");
menu1.setStore(store1);
mockMenus.add(menu1);
Menu menu2 = new Menu();
menu2.setMenuName("Menu 2");
Store store2 = new Store();
store2.setId(2L);
store2.setStoreName("Store 2");
menu2.setStore(store2);
mockMenus.add(menu2);
when(menuRepository.findByMenuNameContaining(keyword)).thenReturn(mockMenus);
when(storeRepository.findByStoreNameContaining(keyword)).thenReturn(mockStores);
// when
List<SearchResponseDto> responseDtos = searchService.searchStoresAndMenusByKeyword(keyword);
// then
assertEquals(mockMenus.size() + mockStores.size(), responseDtos.size());
// 메뉴 검색 결과 확인
for (Menu menu : mockMenus) {
assertTrue(responseDtos.stream().anyMatch(dto -> dto.getType().equals("menu")
&& dto.getStoreName().equals(menu.getStore().getStoreName())));
}
// 가게 검색 결과 확인
for (Store store : mockStores) {
assertTrue(responseDtos.stream().anyMatch(dto -> dto.getType().equals("store")
&& dto.getStoreName().equals(store.getStoreName())));
}
}
}
Java
복사
이 코드에서의 문제점은 Entity에 직접 Setter 메소드가 필요한 점이었다. 이는 테스트 코드를 위해서 실제 프로젝트의 Entity 클래스에 @Setter가 필요해지면서 데이터를 변형 시킬 수 있는 가능성이 높아져서 테스트코드의 의도와는 다르게 의도하지 않은 DB 조작이 발생할 수 있어 올바르지 않다.
따라서 Mockito 모의 객체를 생성하는 방식으로 변경해보았다.
class SearchServiceTest {
@Mock
private MenuRepository menuRepository;
@Mock
private StoreRepository storeRepository;
@InjectMocks
private SearchService searchService;
@BeforeEach
void setUp() {
MockitoAnnotations.initMocks(this);
}
@Test
@DisplayName("메뉴와 가게 이름으로 검색 성공")
public void testSearchStoresAndMenusByKeyword_Success() {
// given
String keyword = "1";
List<Menu> mockMenus = new ArrayList<>();
List<Store> mockStores = new ArrayList<>();
// Mock 객체 생성 및 설정
Menu menu1 = mock(Menu.class);
when(menu1.getMenuName()).thenReturn("Menu 1");
Store store1 = mock(Store.class);
when(store1.getId()).thenReturn(1L);
when(store1.getStoreName()).thenReturn("Store 1");
when(menu1.getStore()).thenReturn(store1);
mockMenus.add(menu1);
Menu menu2 = mock(Menu.class);
when(menu2.getMenuName()).thenReturn("Menu 2");
Store store2 = mock(Store.class);
when(store2.getId()).thenReturn(2L);
when(store2.getStoreName()).thenReturn("Store 2");
when(menu2.getStore()).thenReturn(store2);
mockMenus.add(menu2);
when(menuRepository.findByMenuNameContaining(keyword)).thenReturn(mockMenus);
when(storeRepository.findByStoreNameContaining(keyword)).thenReturn(mockStores);
// when
List<SearchResponseDto> responseDtos = searchService.searchStoresAndMenusByKeyword(keyword);
// then
assertEquals(mockMenus.size() + mockStores.size(), responseDtos.size());
// 메뉴 검색 결과 확인
for (Menu menu : mockMenus) {
assertTrue(responseDtos.stream().anyMatch(dto -> dto.getType().equals("menu")
&& dto.getStoreName().equals(menu.getStore().getStoreName())));
}
// 가게 검색 결과 확인
for (Store store : mockStores) {
assertTrue(responseDtos.stream().anyMatch(dto -> dto.getType().equals("store")
&& dto.getStoreName().equals(store.getStoreName())));
}
}
@Test
@DisplayName("메뉴와 가게 이름으로 검색 실패 - 데이터 없음")
public void testSearchStoresAndMenusByKeyword_Failure_NoData() {
// given
String keyword = "nonexistent";
List<Menu> mockMenus = new ArrayList<>();
List<Store> mockStores = new ArrayList<>();
when(menuRepository.findByMenuNameContaining(keyword)).thenReturn(mockMenus);
when(storeRepository.findByStoreNameContaining(keyword)).thenReturn(mockStores);
// when
List<SearchResponseDto> responseDtos = searchService.searchStoresAndMenusByKeyword(keyword);
// then
assertEquals(0, responseDtos.size());
}
}
Java
복사
Mock객체를 통해서 모의 Menu, Store를 생성할 수 있으며, 객체의 필드 또한 모의 필드값을 입력하면서 마치 DB에 있는 데이터처럼 테스트를 진행 할 수 있다.
기본적인 성공 실패 보다 많은 예외 및 유효성검사 와 관련된 테스트 케이스를 만들어볼 필요가 있다.