프로젝트3

코드 굽는 제빵사·2021년 1월 10일
0

문제 : page반환하는 함수 테스트는 어떻게 할까?

처음엔 지금까지 해온 것 처럼 임의의 page객체를 만들어서 테스트 하면 될 것이라고 생각하고 임의의 page객체를 만들기 위해 검색을 했다 PageImpl 클래스를 활용해서 사용자가 객체를 만들 수 있었다.
그런데 그렇게 하던 중 문제가 생겼다.

@Override
    public Page<StoreUserQueryDto> findByAll(PageRequest pageRequest) {
        Page<StoreUser> AllStoreUser = storeUserRepository.findAll(pageRequest);
        return AllStoreUser.map(this::transferStoreUserToStoreQueryDto);
}

StoreUserQueryDto transferStoreUserToStoreQueryDto(StoreUser storeUser) {
        return new StoreUserQueryDto(
                storeUser.getName(),
                storeUser.getAddress(),
                storeUser.getStore());
}

해결 : PageImpl를 만들거나 Page.class를 모킹하자!

이번 해결 방법은 뭔가 맞지 않는 것 같기도 하지만 두가지의 방법으로 테스트 할 수 있다고 판단했다.

첫번째 테스트에서 확인하고 싶은 것은 repository에서 조회 된 덩어리들이 서비스 계층에서
page.map()를 활용해서 page<StoreUserQueryDto>로 잘 변경 되도록 하는 것이다.
그리고 pagenation이 내가 설정 한대로 작동하는 테스트를 기대했다.

@Test
    public void 전체조회하기() throws Exception {
        //given
        List<StoreUser> storeUsers = new ArrayList<>();
        Address address = createAddress("seoul", "songpa-dong", "4242");
        storeUsers.add(createStoreUser("nakim1", address));
        storeUsers.add(createStoreUser("nakim2", address));
        storeUsers.add(createStoreUser("nakim3", address));
        Page<StoreUser> pageResult = new PageImpl<StoreUser>(storeUsers, PageRequest.of(0, 1), storeUsers.size());
        //when
        when(storeUserRepository.findAll(any(PageRequest.class))).thenReturn(pageResult);
        //then
        Page<StoreUserQueryDto> byAll = storeUserQueryService.findByAll(PageRequest.of(0, 1));
        Assertions.assertEquals(byAll.getTotalElements(), pageResult.getTotalElements());
}

위의 테스트에 byAll.forEach(System.out::println)를 추가해서 보면!

StoreUserQueryDto(name=nakim1, address=chocolate.chocho.entity.Address@10fde30a, store=null)
StoreUserQueryDto(name=nakim2, address=chocolate.chocho.entity.Address@10fde30a, store=null)
StoreUserQueryDto(name=nakim3, address=chocolate.chocho.entity.Address@10fde30a, store=null)

Process finished with exit code 0

분명 page = 0, size = 1이므로 1개의 객체가 탐색되어야 한다고 예상했지만 모든 객체가 출력된다.
그래서 처음엔 함수를 제대로 사용하지 못하는것인지 검색해봐서 여러 해결책이 나왔지만 결론적으론 임의의
page객체에 원래 pagenation이 되지 않는다고 한다. 왜냐하면 쿼리를 통해 가져온 데이터를 위해 설계 된 것이기 때문이다. 내가 원하는 목표인 객체가 제대로 transfer되면 되지 않을까 생각한다.

어디서 주워 들은 말인데 프레임워크를 테스트하지 말라! 라고 어디 공식문서에서 본 것 같다.
그러므로 page가 갯수가 제대로 나오는지 테스트하지 않아도 되지 않을까 생각이 든다.
매개변수만 제대로 주어진다면 제대로 된 pagenation이 될테니까 말이다.

두번째 해결 방법은 Mock을 활용해서 Page.class를 모킹하는 것인데 Repository를 호출 할때 모킹된 Page를 주어서 하는 것인데 이 방법은 pageStub의 storeUser가 null이기 transfer함수를 검증 할 수 없다. 그렇지만 아래와 같은 방법으로도 진행하는 것 같아 참고 사항으로 적어둔다!

@Test
    public void 전체조회하기() throws Exception {
        //given
        Page<StoreUser> pageStub = (Page<StoreUser>)Mockito.mock(Page.class);
        //when
        when(storeUserRepository.findAll(any(PageRequest.class))).thenReturn(pageStub);
        //then
        Page<StoreUserQueryDto> byAll = storeUserQueryService.findByAll(PageRequest.of(1, 20));
    }

이번 테스트에서 얻은 교훈은 레퍼런스를 잘 참고해서 해야한다는 것이다. 사용자 단계에서 사용하지 않는 class라고 한다. 그렇다면 page가 포함되어 있을 땐 어떻게 테스트 하는지 추후에 자세히 알아봐야겠다.

공식 문서
DataJPA 깃허브 이슈

그 외
Mocking page.class하는 방법

0개의 댓글