โ๏ธ์๋ฌ ๋ฉ์์ง
java.lang.AssertionError: Expecting actual not to be null
๐ป ๊ฐ๋ฐ ํ๊ฒฝ
- Framework : Spring Boot `3.2.3`
- DB : MySQL(๋ก์ปฌ), H2(ํ ์คํธ)
- Library : JPA, QueryDSL `5.0.0`
- Test : JUnit
๐ ์์ธ
Spring์์ Junit์ผ๋ก Service ๋จ์ ๊ฒ์๊ธ ๋ฑ๋ก ๊ธฐ๋ฅ์ ํ ์คํธํ๋๋ฐ ์๋ฌ๊ฐ ๋ฌ๋ค.
๊ฒ์๊ธ ๋ฑ๋ก ๋ฉ์๋๋ `save()`๋ฅผ ์ํํ๊ณ , ์๋ก ๋ฑ๋ก๋ ๊ฒ์๊ธ์ `id`๋ฅผ ๋ฐํํ๋ค.
์ด๋ฅผ ํ ์คํธํ๊ธฐ ์ํด Mock ๊ฐ์ฒด๋ฅผ ๋ง๋ค์ด `save()`๋ฅผ ์ํํ๋ฉด ๋ฐํํ๋๋ก ํ๊ณ , `getId()`๋ฅผ ํธ์ถํ๋ฉด `id`๋ก 1L์ ๋ฐํํ๋๋ก ์ค์ ํ๋ค. ๊ทธ๋ฆฌ๊ณ ๊ฒ์๊ธ ๋ฑ๋ก ๋ฉ์๋๋ฅผ ์คํํ์ ๋ ๋ฐํ๊ฐ์ด ์ค์ ํ `id` ๊ฐ๊ณผ ๊ฐ์์ง๋ฅผ ๊ฒ์ฆํ๋ ์ฝ๋๋ฅผ ์์ฑํ๋ค.
@Test
@DisplayName("๊ตฌ์ง ๊ฒ์๊ธ ์์ฑ")
public void createHiringPostTest() {
// given
HiringPostReq hiringPostReq = HiringPostReq.builder()
...
.build();
...
HiringPost mockHiringPost = mock(HiringPost.class);
when(hiringPostRepository.save(any(HiringPost.class))).thenReturn(mockHiringPost);
when(mockHiringPost.getId()).thenReturn(1L);
// when
Long resultId = hiringPostServiceImpl.registerHiringPost(hiringPostReq);
//๊ฐ์ฒด ํ์ธ์ ์ํ print
HiringPost savedHiringPost = hiringPostRepository.save(any(HiringPost.class));
System.out.println("hiringPost: " + savedHiringPost);
System.out.println("resultId: " + resultId);
// then
assertThat(resultId).isNotNull();
assertThat(resultId).isEqualTo(1L);
...
verify(hiringPostRepository, times(1)).save(any(HiringPost.class));
}
์ ๋๋ก `save()`์ `getId()` ๋ฉ์๋๊ฐ ์คํ๋์๋์ง ํ์ธํ๊ธฐ ์ํด์ ํ๋ฆฐํธ๋ฅผ ์ฐ์ด๋ดค๋ค.
`save()`๊ฐ ํธ์ถ๋๋ฉด ๊ฒฐ๊ณผ๊ฐ์ผ๋ก `null`์ด ๋์๊ณ , `getId()`๋ฅผ ํธ์ถํ๋ ์๋น์ค ๋ฉ์๋ ๊ฒฐ๊ณผ๊ฐ์ธ `resultId`๊ฐ null์ด ๋์๋ค.
์๋น์ค์์ `save()`๊ฐ ํธ์ถ๋ ๋, Mockito๊ฐ Mock ๊ฐ์ฒด(mockHiringPost)๋ฅผ ๋ฐํํ์ง ์๋ ๊ฒ์ด๋ค. ์๋น์ค ๋ฉ์๋์ ๋ด๋ถ์์ ์๋ก ์์ฑ๋ ๊ฐ์ฒด(HiringPost)๋ฅผ ๋ฐํํ๋ค.
Mock ๊ฐ์ฒด์ ์ค์ ๊ฐ์ฒด๊ฐ ํผ์ฉ์ด ๋๊ณ ์์๋ค.. (์ง๊ธ ํฌ์คํ ์ ์ฐ๋ ์๊ฐ์๋ ํท๊ฐ๋ฆฐ๋ค๐ )
๐ก ํด๊ฒฐ
`save()`๊ฐ ํธ์ถ๋ ๋, Mock ๊ฐ์ฒด๊ฐ ์๋๋ผ ์ค์ ๊ฐ์ฒด๊ฐ ์ฌ์ฉ๋๋๋ก ํ๋ค.
๊ทธ๋ฆฌ๊ณ ์ค์ ๊ฐ์ฒด์ id ๊ฐ์ ์ค์ ํด์ค๋ค.
when(hiringPostRepository.save(any(HiringPost.class))).thenAnswer(invocation -> {
HiringPost hiringPost = invocation.getArgument(0);
ReflectionTestUtils.setField(hiringPost, "id", 1L);
return hiringPost;
});
- ๋์์ ๋ ์์ธํ ์ ์ํ๊ธฐ ์ํด์ `thenAnswer`์ ์ฌ์ฉํ๋ค. `invocation`์ ๋ฉ์๋๋ฅผ ํธ์ถํ ๋, ๋ฐํ๊ฐ์ ๊ฐ์ ธ์ ๋์์ ์ค์ ํ ์ ์๋๋ก ํด์ค๋ค.
- `invocation.getArgument(0)`์ ๊ฒฐ๊ณผ๋ก ์ ์ฅํ๋ ค๋ HiringPost ๊ฐ์ฒด๋ฅผ ๊ฐ์ ธ์ค๊ฒ ๋๋ค.
- ์๋์ผ๋ก id๊ฐ ์์ฑ๋์ง ์๊ธฐ ๋๋ฌธ์ ์ง์ id๋ฅผ ์ค์ ํด์ค์ผ ํ๋ค.
id ์ค์ ๋ถ๋ถ์์ `ReflectionTestUtils`์ ์ฌ์ฉํด์ผ ํ๋ค.
๊ฐ์ฒด์ ํ๋๊ฐ private์ผ๋ก ์ ์๋์ด ์๊ธฐ๋ ํ๊ณ , ์ธ๋ถ์์ ๊ฐ์ ๋ณ๊ฒฝํ ์ ์๋๋ก setter ์ฌ์ฉ์ ๋ง์๊ธฐ ๋๋ฌธ์ด๋ค.