- @SpringBootTest를하면 모든것이 다 빈으로 등록이 되니까 자연스럽게 테스트가 됨
- @WebMvcTest 사용하면 컨트롤러만 빈으로 등록이되서 ArgumentResolver랑 JwtFilter 를 수동으로 등록을 해줘야 작동을 한다!
- JpaMetamodelMappingContext : Spring Data JPA의 자동 설정 중 하나인 JpaMetamodelMappingContext가 없어 생기는 빈 등록 예외를 방지하기 위해서 주입
- 또한 컨트롤러는 Argument Resolver랑 Converter 같은걸 거치니까 새로운 객체가 생겨서 eq로 내용이 동일한지 확인해줘야함
기존에 @WebMvcTest를 사용했는데 수동으로 등록하지않았다면 AuthUser에 필드가 다 null이었음 ⇒ any()를 써버리니까 통과가 되었던 것!
결론 : 그래서 Filter랑,Argument Resolver를 등록하고 하니까 AuthUser가 정상적으로 만들어지고 컨트롤러 테스트가 잘 통과 된다!
@WebMvcTest(AlarmController.class)
@TestPropertySource(properties = {
"jwt.secret.key=5Gk6hibHDtKLFVk4NdBX039rvehSLNjfKsdXpm/pHsU="
})
@Import({JwtUtil.class, AuthUserArgumentResolver.class, JwtFilter.class})
class AlarmControllerTest {
@Autowired
MockMvc mockMvc;
@MockitoBean
JpaMetamodelMappingContext jpaMetamodelMappingContext;
@MockitoBean
AlarmService alarmService;
@Autowired
JwtUtil jwtUtil;
AlarmHistories histories1;
AlarmHistories histories2;
@BeforeEach
void setUp() {
histories1 = AlarmHistories.of(
"회원님의 글에 댓글이 달렸습니다",
1L,
AlarmType.COMMENT
);
ReflectionTestUtils.setField(histories1, "id", 1L);
ReflectionTestUtils.setField(histories1, "createdAt", LocalDateTime.now());
histories2 = AlarmHistories.of(
"회원님의 글에 댓글이 달렸습니다",
1L,
AlarmType.COMMENT
);
ReflectionTestUtils.setField(histories2, "id", 2L);
ReflectionTestUtils.setField(histories2, "createdAt", LocalDateTime.now());
}
@Test
public void 알람_내역을_페이징을_이용하여_조회한다() throws Exception {
// given
int page = 0;
int size = 10;
int totalElement = 2;
int totalPages = 1;
Pageable pageable = PageRequest.of(page,size);
Long userId = 1L;
UserRole userRole = UserRole.PATIENT;
AuthUser authUser = AuthUser.of(userId, userRole);
String accessToken = jwtUtil.createToken(userId, userRole);
List<AlarmHistories> alarmHistories = new ArrayList<>();
alarmHistories.add(histories1);
alarmHistories.add(histories2);
List<AlarmResponse> alarmResponses = AlarmResponse.toAlarmResponse(alarmHistories);
PageInfo pageInfo = PageInfo.builder()
.pageNum(page)
.pageSize(size)
.totalElement(totalElement)
.totalPage(totalPages)
.build();
PageResult<AlarmResponse> pageResult = new PageResult<>(alarmResponses, pageInfo);
given(alarmService.findAlarms(refEq(authUser) // 필드값 비교
, argThat(p -> p.getPageNumber() == pageable.getPageNumber() && p.getPageSize() == pageable.getPageSize()))) // 페이징 객체 값만 비교
.willReturn(pageResult);
// when & then
mockMvc.perform(get("/api/v1/notifications")
.param("page", "0")
.param("size", "10")
.header("Authorization", accessToken))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.data[0].id").value(histories1.getId()))
.andExpect(MockMvcResultMatchers.jsonPath("$.data[0].content").value(histories1.getContent()))
.andExpect(MockMvcResultMatchers.jsonPath("$.data[0].alarmType").value(histories1.getAlarmType().name()))
.andExpect(MockMvcResultMatchers.jsonPath("$.data[1].id").value(histories2.getId()))
.andExpect(MockMvcResultMatchers.jsonPath("$.data[1].name").value(histories2.getContent()))
.andExpect(MockMvcResultMatchers.jsonPath("$.data[1].alarmType").value(histories2.getAlarmType().name()))
.andExpect(MockMvcResultMatchers.jsonPath("$.page.pageNum").value(page))
.andExpect(MockMvcResultMatchers.jsonPath("$.page.pageSize").value(size))
.andExpect(MockMvcResultMatchers.jsonPath("$.page.totalElement").value(totalElement))
.andExpect(MockMvcResultMatchers.jsonPath("$.page.totalPage").value(totalPages));
}
}
'Spring' 카테고리의 다른 글
FCM 알람 전송 재시도 구현하기 (0) | 2025.05.14 |
---|---|
FCM의 구조와 이를 구현하기 위한 고민(Feat : FCM토큰관리와 전송 메서드) (1) | 2025.05.12 |
알람 전송 구현 기술의 고민 (0) | 2025.05.12 |
동적쿼리와 인덱싱 적용하여 성능 개선하기 (+ Like 검색은?) (0) | 2025.04.07 |
컨트롤러 테스트 작성시 주의할 점 (1) | 2025.04.07 |