[TEST] 테스트하는데 MOCK 이 이상하게 작동한다

onyoo·2024년 4월 25일
0

Spring-Boot

목록 보기
6/6

사건의 발단

TDD로 코드를 작성하던 중 테스트 코드에 작성한 Service Layer의 Mock이 내 의도와는 다르게 작동하였다.

문제상황

	@Test
	public void 유저생성() throws Exception {
		long id = 1L;
		String username = "test@email.com";
		String password = "test";
		String intro = "hello?";
		String nickname = "test";
		String profile = "image";

		MemberRequest memberRequest = MemberRequest.builder()
			.username(username)
			.password(password)
			.introduce(intro)
			.nickname(nickname)
			.profileImage(profile)
			.build();

		String json = objectMapper.writeValueAsString(memberRequest);

		MemberResponse memberResponse = MemberResponse.builder()
			.username(username)
			.introduce(intro)
			.nickname(nickname)
			.profileImage(profile)
			.build();

		when(memberService.addMember(memberRequest)).thenReturn(memberResponse);

		mockMvc.perform(
				post("/api/v1/members").contentType(MediaType.APPLICATION_JSON).content(json).with(csrf())
			)
			.andExpect(
				status().isOk()
			)
			.andExpect(
				jsonPath("$.data.username").value(username)
			)
			.andExpect(
				jsonPath("$.data.nickname").value(nickname)
			);
	}

when(memberService.addMember(memberRequest)).thenReturn(memberResponse);

이렇게 Mocking을 해서 service layer의 리턴값을 지정해주었다.

@PostMapping()
	ResponseEntity<CustomResponse<MemberResponse>> memberAdd(@RequestBody MemberRequest memberRequest) {
		MemberResponse memberResponse = memberService.addMember(memberRequest);
		return ResponseEntity.ok(new CustomResponse<>(HttpStatus.OK.value(), "유저가 성공적으로 추가되었습니다", memberResponse));
	}

그렇게 하면 controller에서 입력받은 memberRequest 를 가지고 memberService.addMember(memberRequest) 이 작동해야한다.

해당 코드가 작동하는 순간 내가 작성한 mock 의 값을 리턴해야한다.

이상하게도 내가 controller에 memberRequest 는 제대로 도착하고 값도 정확했는데 이상하게 서비스 레이어에 도착하면 memberResponse 가 null이 되어버리는 현상이 발생했다.

응답은 성공적으로 하나 data 에는 null 값이 담겼다!

답은 아래의 블로그에서 찾을 수 있었다.

[Test] Mockito.when() 사용 시 설정한 리턴 값이 나오지 않는 에러

테스트 코드 내부에서 요청한 값으로 보낸 DTO의 값과 컨트롤러 내부에 있는 DTO의 해시코드가 일치하지 않았던 것이다.

when(memberService.addMember(memberRequest)).thenReturn(memberResponse);

그래서 mock에서 입력으로 받은 객체의 해시코드가 다르기 때문에 mock이 작동하지 않은 것이다.

해결방법

여기서 문제가 되는 상황은 객체의 값이 같아도 다른 해시코드를 생성하는 것이 문제였다.

이러한 부분을 해결하려면 객체의 값이 같으면 같은 해시값을 가지게 하면 되는 것이다.

그러한 부분을 해결해주는 어노테이션 @EqualsAndHashCode 를 DTO에 달아주면 된다.

(직접 구현해도 상관 X)

profile
반갑습니다 ! 백엔드 개발 공부를 하고있습니다.

0개의 댓글