[Testing] Mockito
Categories: Spring
๐ ๊ฐ์ธ์ ์ธ ๊ณต๊ฐ์ผ๋ก ๊ณต๋ถ๋ฅผ ๊ธฐ๋กํ๊ณ ๋ณต์ตํ๊ธฐ ์ํด ์ฌ์ฉํ๋ ๋ธ๋ก๊ทธ์
๋๋ค.
์ ํํ์ง ์์ ์ ๋ณด๊ฐ ์์ ์ ์์ผ๋ ์ฐธ๊ณ ๋ฐ๋๋๋ค :๐ธ
[ํ๋ฆฐ ๋ด์ฉ์ ๋๊ธ๋ก ๋จ๊ฒจ์ฃผ์๋ฉด ๋ณต๋ฐ์ผ์ค๊ฑฐ์์]
Mockito
โ Mock ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ์ง ์์ ์ฌ๋ผ์ด์ค ํ ์คํธ ํ๋ก์ธ์ค
โ Mock ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ ์ฌ๋ผ์ด์ค ํ ์คํธ ํ๋ก์ธ์ค
Mockito๋?
- Spring Framework ์์ฒด์ ์ผ๋ก๋ ์ง์ํ๊ณ ์๋ Mocking ๋ผ์ด๋ธ๋ฌ๋ฆฌ โ Mockito
- Mock ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ , ํด๋น Mock ๊ฐ์ฒด๊ฐ ์ง์ง์ฒ๋ผ ๋์ํ๊ฒ ํ๋ ์ญํ ์ ๋ด๋น
- Mockito์ Mocking ๊ธฐ๋ฅ์ ์ด์ฉํด์ ํ
์คํธํ๊ณ ์ ํ๋ ๋์์์
๋ค๋ฅธ ์์ญ(๋ค๋ฅธ ๊ณ์ธต ๋๋ ์ธ๋ถ ํต์ ์ด ํ์ํ ์๋น์ค ๋ฑ)์ ๋จ์ ์์ผ ์ค๋ก์ง ํ ์คํธ ๋์์๋ง ์ง์ค ๊ฐ๋ฅ
์ฌ๋ผ์ด์ค ํ ์คํธ์ Mockito ์ ์ฉ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
@Test
void postMemberTest() throws Exception {
// given
//MemberDto.Post ๊ฐ์ฒด๋ฅผ ์์ฑํ์ฌ ํ
์คํธ์ ์ฌ์ฉํ ๋ฐ์ดํฐ๋ฅผ ์ค์
MemberDto.Post post = new MemberDto.Post("jerry@gmail.com","์ ๋ฆฌ","010-1111-1111");
// ์์ฑ๋ MemberDto.Post ๊ฐ์ฒด๋ฅผ Member ๊ฐ์ฒด๋ก ๋ณํํฉ๋๋ค.
Member member = mapper.memberPostToMember(post);
// ๋ณํ๋ Member ๊ฐ์ฒด์ ID๋ฅผ ์ค์
//์๋๋ฉด createMember์์ Id๋ฅผ ๋ฆฌํดํด์ฃผ๊ณ
// Id๊ฐ response์์๋ Location header์ ํฌํจ์ด๋์ด์ผ ํจ
member.setMemberId(1L);
// memberService.createMember ๋ฉ์๋๊ฐ
//์ด๋ค Member ๊ฐ์ฒด๋ฅผ ๋ฐ๋๋ผ๋ ๋ฏธ๋ฆฌ ์ค์ ํ member ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋๋ก mock ์ค์
given(memberService.createMember(Mockito.any(Member.class)))
.willReturn(member);
// post ๊ฐ์ฒด๋ฅผ JSON ๋ฌธ์์ด๋ก ๋ณํ
String content = gson.toJson(post);
// when -> /v11/members์ POST ์์ฒญ์ ๋ณด๋ด๊ธฐ
ResultActions actions = mockMvc.perform(post("/v11/members")
.accept(MediaType.APPLICATION_JSON) // ์๋ต์ JSON ํ์์ผ๋ก ๋ฐ๊ฒ ๋ค๋ ์๋ฏธ.
.contentType(MediaType.APPLICATION_JSON) // ์์ฒญ ๋ณธ๋ฌธ์ด JSON ํ์์ด๋ผ๋ ๊ฒ
.content(content)); // ์์ฒญ ๋ณธ๋ฌธ์ ๋ณํ๋ JSON ๋ฌธ์์ด์ ํฌํจ์ํจ๋ค.
// then: ๊ฒฐ๊ณผ๋ฅผ ๊ฒ์ฆํ๋ ๋ถ๋ถ
actions.andExpect(status().isCreated())
// ์๋ต ํค๋์ Location ๊ฐ์ด "/v11/members/"๋ก ์์ํ๋์ง ํ์ธ
.andExpect(header().string("Location", is(startsWith("/v11/members/"))));
}
@MockBean
- Application Context์ ๋ฑ๋ก๋์ด ์๋ Bean์ ๋ํ Mockito Mock ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ ์ฃผ์
ํด ์ฃผ๋ ์ญํ ์ ํ๋ค
โ@MockBean
์ ๋ํ ์ด์ ์ ํ๋์ ์ถ๊ฐํ๋ฉด ํด๋น ํ๋์ Bean์ ๋ํ Mock ๊ฐ์ฒด๋ฅผ ์์ฑํ ํ,
ํ๋์ ์ฃผ์ (DI)ํ๋ค.. - ์์ ์ฝ๋์์๋ MemberService ๋น์ ๋ํ Mock ๊ฐ์ฒด๋ฅผ ์์ฑํด์ memberService ํ๋์ ์ฃผ์ ํ๋ค.
- Application Context์ ๋ฑ๋ก๋์ด ์๋ Bean์ ๋ํ Mockito Mock ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ณ ์ฃผ์
ํด ์ฃผ๋ ์ญํ ์ ํ๋ค
- MemberMapper
- DI ๋ฐ๋ ์ด์ ๋ MockMemberService(๊ฐ์นญ)์
createMember()
์์ ๋ฆฌํดํ๋ Member ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ธฐ ์ํจ
โ post(MemberDto.Post ํ์ ) ๋ณ์๋ฅผ Member ๊ฐ์ฒด๋ก ๋ณํ - new Member()์ ๊ฐ์ด Member ๊ฐ์ฒด๋ฅผ ์์ฑํด๋ ๋์ง๋ง post ๋ณ์๋ฅผ ์ฌ์ฌ์ฉํ๊ธฐ ์ํด MemberMapper๋ก ๋ณํ ํจ.
- ์ค์ createMember()์ ๋ฆฌํด ๊ฐ(Member ๊ฐ์ฒด)์๋ memberId๊ฐ ํฌํจ์ด ๋๋๋ฐ
์ด memberId๋ response์ Location header์ ํฌํจ์ด ๋์ด์ผ ํ๋ฏ๋ก MockMemberService(๊ฐ์นญ)์ createMember()์์๋
memberId๋ฅผ ๋ฆฌํดํด ์ค ์ ์๋๋ก memberId๋ฅผ ์ถ๊ฐํจ.
- DI ๋ฐ๋ ์ด์ ๋ MockMemberService(๊ฐ์นญ)์
-
Stubbing ๋ฉ์๋(Mockito์์ ์ง์)
-
๐คStubbing์ด๋? - ํ ์คํธ๋ฅผ ์ํด์ Mock ๊ฐ์ฒด๊ฐ ํญ์ ์ผ์ ํ ๋์์ ํ๋๋ก ์ง์ ํ๋ ๊ฒ์ ์๋ฏธ
-
given()
์ Mock ๊ฐ์ฒด๊ฐ ํน์ ๊ฐ์ ๋ฆฌํดํ๋ ๋์์ ์ง์ ํ๋ ๋ฐ ์ฌ์ฉํ๋ฉฐ,
Mockito์์ ์ง์ํ๋when()
๊ณผ ๋์ผํ ๊ธฐ๋ฅ์ ํฉ๋๋ค.์ฌ๊ธฐ์๋ Mock ๊ฐ์ฒด์ธ memberService ๊ฐ์ฒด๋ก createMember() ๋ฉ์๋๋ฅผ ํธ์ถํ๋๋ก ์ ์ํ๊ณ ์๊ณ , ํ๋ผ๋ฏธํฐ์ธ
Mockito.any(Member.class)
๋ Mockito์์ ์ง์ํ๋ ๋ณ์ ํ์ ์ค ํ๋์ด๋ค.
ํ๋ผ๋ฏธํฐ๋ ์ค์ ๋ฉ์๋์์ ๋ค์ด๊ฐ๋ ํ๋ผ๋ฏธํฐ์ ํ์ ์ ์ง์ ํด์ฃผ๋ฉด ๋๋๋ฐ Mockito.any( )์ ๊ฐ์ธ์ ๋ฃ์ด์ฃผ๋ฉด ๋จ.- ๊ฐ์ฒด์ผ ๊ฒฝ์ฐ๋ ์๊ธฐ ์ฝ๋์ฒ๋ผ Mockito.any(๊ฐ์ฒด๋ช .class)
- long type์ ๊ฒฝ์ฐ Mockito.anyLong()
- int type์ ๊ฒฝ์ฐ Mockito.anyInt()
- String type์ ๊ฒฝ์ฐ Mockito.anyString()
-
.willReturn(member)
MockMemberService(๊ฐ์นญ)์ createMember() ๋ฉ์๋๊ฐ ๋ฆฌํดํ Stub ๋ฐ์ดํฐ
-
Debugging ํ๊ณ memberService๋ฅผ ๋ณด๋ฉด MockitpMock์ผ๋ก ๊ฐ์ง ๊ฐ์ฒด๊ฐ ๋ค์ด์์๋ค.
-
์๋น์ค ๋จ์ํ ์คํธ์ Mockito ์ ์ฉ
- ์ผ๋ฐ์ ์ผ๋ก ๋น์ฆ๋์ค ๋ก์ง์ ๋ฐ์ดํฐ ์ก์ธ์ค ๊ณ์ธต๊ณผ๋ ๋ฌด๊ดํ๊ฒ ์๋น์ค ๊ณ์ธต์ ๊ตฌํ๋ ๋น์ฆ๋์ค ๋ก์ง ์์ฒด๋ฅผ Spring Framework์ ๋์์ ๋ฐ์ง ์๊ณ ๋ ๋น ๋ฅด๊ฒ ํ ์คํธ๋ฅผ ์งํํ ์ ์์ด์ผํ๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
package com.springboot.member.service;
import com.springboot.exception.BusinessLogicException;
import com.springboot.member.entity.Member;
import com.springboot.member.repository.MemberRepository;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import java.util.Optional;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.BDDMockito.given;
// ๋จ์ ํ
์คํธ์์ Mockito๋ฅผ ์ฌ์ฉํ ๋ ํ์ํ ์ด๋
ธํ
์ด์
//MockitoExtension ๊ธฐ๋ฅ์ ํ์ฅํ๊ฒ ๋ค๋ ์๋ฏธ
@ExtendWith(MockitoExtension.class)
class MemberServiceMockTest {
@Mock // MockBean๊ณผ๋ ๋ค๋ฆ. ์คํ๋ง ์ปจํ
์ด๋์ ๋์์ด ํ์ ์์ด์ ์ฌ์ฉ
private MemberRepository memberRepository;
@InjectMocks
// ํ
์คํธํด์ผ ํ ๊ฐ์ฒด์ ์ฃผ์
ํด์ผ ํ๋ค.
//๊ฐ์ง Repository๋ฅผ ์์กดํ๋ ์๋น์ค๋ฅผ ์ฃผ์
ํ๋ ๊ฒ.
private MemberService memberService;
@Test
public void createMemberTest(){
// given
// ์๋ก์ด Member ๊ฐ์ฒด๋ฅผ ์์ฑํ์ฌ ํ
์คํธ ๋ฐ์ดํฐ๋ก ์ฌ์ฉํฉ๋๋ค.
Member member = new Member("jerry@gmail.com", "์ ๋ฆฌ", "010-4111-1111");
// when
// memberRepository์ findByEmail ๋ฉ์๋๊ฐ ์ด๋ค ๋ฌธ์์ด์ ๋งค๊ฐ๋ณ์๋ก ๋ฐ์๋,
//ํญ์ Optional.of(member)๋ฅผ ๋ฐํํ๋๋ก ์ค์ ํฉ๋๋ค.
given(memberRepository.findByEmail(Mockito.anyString())).willReturn(Optional.of(member));
// then
// createMember ๋ฉ์๋๋ฅผ ํธ์ถํ์ ๋ BusinessLogicException ์์ธ๊ฐ ๋ฐ์ํ๋์ง ํ์ธ
// ์ด ํ
์คํธ๋ ์ด๋ฉ์ผ์ด ์ค๋ณต๋๋ ๊ฒฝ์ฐ ์์ธ๊ฐ ๋ฐ์ํ๋์ง๋ฅผ ํ์ธํ๋ ํ
์คํธ
assertThrows(BusinessLogicException.class, () -> memberService.createMember(member));
}
}
-
memberRepository Mock ๊ฐ์ฒด๋ก Stubbing์ ํ๊ณ ์์.
memberRepository.findByEmail(Mockito.anyString())
์ ๋ฆฌํด ๊ฐ์ผ๋ก
Optional.of(member)
๋ฅผ ์ง์ ํ๊ธฐ ๋๋ฌธ์ ํ ์คํธ ์ผ์ด์ค๋ฅผ ์คํํ๋ฉด ๊ฒฐ๊ณผ๋ โpassed
โ์ด๋ค. -
Optional.of(member)์ member ๊ฐ์ฒด์ ํฌํจ๋ ์ด๋ฉ์ผ ์ฃผ์๊ฐ memberService.createMember(member)์์
ํ๋ผ๋ฏธํฐ๋ก ์ ๋ฌํ member ๊ฐ์ฒด์ ํฌํจ๋ ์ด๋ฉ์ผ ์ฃผ์์ ๋์ผํ๊ธฐ ๋๋ฌธ์ ๊ฒ์ฆ ๊ฒฐ๊ณผ๊ฐ โpassedโ
Comment
์ฒ์์ ์์
์ด ๋๋ฌด ๋น ๋ฅด๊ฒ ์งํ๋์ ์ดํด๋ฅผ ๋ชปํด์ ์ฝ๋์ ํ๋ ํ๋ ์ฃผ์๋ฌ๊ณ
๋ฌผ์ด๋ณด๊ณ ํด์ ์กฐ๊ธ ์ดํด๋์๋๋ฐ
๋ง์ ๋ ์ฐ๋ ค๊ณ ํ๋ฉด ๋ค ๋จ์ ์ํค๊ณ ํด์ผํ๋๊น
์ด๋ป๊ฒ ํ
์คํธ๋ฅผ ํด์ผํ๋ ๊ฑด์ง๋ ์์ง ์ ๋ชจ๋ฅด๊ฒ ๋ค..
ํนํ ์ปจํธ๋กค๋ฌ์ ๊ฒฝ์ฐ์๋ ์ปจํธ๋กค๋ฌ์ ๊ธฐ๋ฅ๋ง ํ
์คํธํ๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์
๋น์ฆ๋์ค ๋ก์ง์ ์งํํ ํ์๊ฐ ์๊ณ ์๋ต๊ณผ ์์ฒญ์ด ์ ์งํ๋๋์ง๋ฅผ ํ
์คํ
ํ๋ ๊ฒ์ด๋ผ๊ณ ํ๋คโฆ.!
ํ์ฌ์์๋ ์ฃผ๋์ด๋ถ๋ค์ ์ด๋ ค์์ Mockito๋ฅผ ์ ์ํ๋ค๊ณ ๊ทธ๋งํผ ์ด๋ ต๊ณ ํ๋ ๊ฑฐ ๋ง์ผ๋๊น
๋ช์๊ฐ์ด๋ผ๋ ์ดํดํ๊ณ ๋
ธ๋ ฅํ๋ ๊ฒ์ด ์ค์ํ๋ค๊ณ ํ์
์ ์ด์ฌํ ๋ด์ผ๊ฒ ๋ค๐
Leave a comment