βοΈ λͺ©μ (Mock-up)
- μ€μ μ νμ΄ λμ€κΈ° μ μ λ΄λΆμ μΌλ‘ μ¬μ©νκΈ° μν λͺ¨ν(κ°μ§) μ ν
- ν μ€νΈ μΈκ³μμλ κ°μ§ κ°μ²΄λ₯Ό μλ―Έ
βοΈ Mocking
- λ¨μ ν μ€νΈλ μ¬λΌμ΄μ€ ν μ€νΈ λ±μ Mock κ°μ²΄λ₯Ό μ¬μ©νλ κ²
Mock κ°μ²΄λ₯Ό μ¬μ©νμ§ μκ³ MemberController ν μ€νΈ μ€ postMember ν μ€νΈλ₯Ό μ§ννλ€κ³ νλ©΄ μ΄μ νλ¦μ μλμ κ°μ κ²μ
- MemberControllerTest ν΄λμ€ λ΄μ
postMemberTest()
- MemberController ν΄λμ€ λ΄μ
postMember()
- MemberService ν΄λμ€ λ΄μ
createMember()
- MemberRepository μΈν°νμ΄μ€ λ΄μ
save()
- H2
- λ€μ λ°λλ‘ μ λμκ°μ ν μ€νΈ μΌμ΄μ€μ λλ¬
But, μ΄λ κ±°μ λͺ¨λ κ³μΈ΅μ λκ³ μ€κΈ° λλ¬Έμ μμ ν μ¬λΌμ΄μ€ ν μ€νΈκ° μλ, ν΅ν©ν μ€νΈμ κ°κΉμ
β β Mock κ°μ²΄λ₯Ό μ¬μ©νμ¬ λ€λ₯Έ κ³μΈ΅κ³Ό λ¨μ μ μμΌμ£Όμ΄
μ΄ κ³Όμ μ μ€μ¬μ£Όκ³ μ¬λΌμ΄μ€ ν
μ€νΈλ₯Ό μ μ©ν μ μλλ‘ ν κ² !
- MemberControllerTest ν΄λμ€ λ΄μ
postMemberTest()
- MemberController ν΄λμ€ λ΄μ
postMember()
- MockMemberService ν΄λμ€ λ΄μ
createMember()
- λ€μ λ°λλ‘ μ λμκ°μ ν μ€νΈ μΌμ΄μ€μ λλ¬
Mock κ°μ²΄λ₯Ό μμ±νκ³ ν΄λΉ Mock κ°μ²΄κ° μ§μ§μ²λΌ λμνκ² νλ κΈ°λ₯μ νλ Mocking framework(λλ λΌμ΄λΈλ¬λ¦¬)
Mockitoμ Mocking κΈ°λ₯μ μ΄μ©ν΄μ ν μ€νΈνκ³ μ νλ λμμμ λ€λ₯Έ μμ(λ€λ₯Έ κ³μΈ΅ λλ μΈλΆ ν΅μ μ΄ νμν μλΉμ€ λ±)μ λ¨μ μμΌ μ€λ‘μ§ ν μ€νΈ λμμλ§ μ§μ€ν μ μκ² ν¨
[μ°Έκ³ ] https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html
https://javacan.tistory.com/entry/MocktestUsingMockito
[Mockito λ©μλλ€ μ°Έκ³ ] https://jdm.kr/blog/222
[Mockito μ§μ Matchers μ°Έκ³ ] https://www.javadoc.io/doc/org.mockito/mockito-core/1.10.19/org/mockito/Matchers.html
given(Mock κ°μ²΄ ν΄λμ€λͺ
.λ©μλλͺ
(Mockito.any(κ°μ²΄νμ
.class))).willReturn(κ°μ²΄λͺ
)
Mockito.any()
λ μ΄λ€ νμ
μΌλ‘ νΈμΆλ μ§ μ§μ .willReturn()
μ μμ ν΄λΉ λ©μλκ° λ¦¬ν΄ν Stub λ°μ΄ν°βοΈ Stubbing
- ν μ€νΈλ₯Ό μν΄μ Mock κ°μ²΄κ° νμ μΌμ ν λμμ νλλ‘ μ§μ νλ κ²
βοΈ Stub
- νΈμΆμ νμ μ ν΄μ§ νλμ νκ±°λ μ ν΄μ§ λ°μ΄ν°λ₯Ό λλ €μ£Όλ μ»΄ν¬λνΈ
- μ£Όλ‘ ν μ€νΈμμ μ¬μ©νκΈ° λλ¬Έμ Test Stubμ΄λΌκ³ ν¨
1. MemberControllerμ postMember() ν μ€νΈμ Mockito μ μ©
@MockBean
μ λν
μ΄μ
μ μ¬μ©νμ¬ κ°μ§ κ°μ²΄λ‘ λ§λ€ Service ν΄λμ€ μ§μ ν, νλμ DI[@MockBean μ°Έκ³ ] https://howtodoinjava.com/spring-boot2/testing/spring-mockbean-annotation/
@Autowired
μ λν
μ΄μ
μ μ¬μ©νμ¬ Dto ν΄λμ€λ₯Ό κ°μΈμ μμ²/μλ΅μ μ²λ¦¬ν mapper ν΄λμ€λ₯Ό νλμ DIEx. MemberControllerMockTest ν΄λμ€μ postMemberTest()
λ₯Ό νΈμΆνμ¬ μ€νν κ²°κ³Ό
β MockMemberServiceμ createMember()
λ©μλκ° νΈμΆλλ―λ‘, λ°μ΄ν° μ‘μΈμ€ κ³μΈ΅μͺ½μ λ‘μ§μ μ€νμ΄ λμ§ μμ
β MockMemberService ν΄λμ€λ μ°λ¦¬κ° ν μ€νΈνκ³ μ νλ Controllerμ ν μ€νΈμ μ§μ€ν μ μλλ‘ λ€λ₯Έ κ³μΈ΅κ³Όμ μ°λμ λμ΄μ£Όλ μν μ νλ κ²
2. MemberServiceμ createMember() ν μ€νΈμ Mockito μ μ©
ν΄λμ€ λ 벨μ @ExtendWith(MockitoExtension.class) μ μ©
β Springμ μ¬μ©νμ§ μκ³ , Junitμμ Mockitoμ κΈ°λ₯μ μ¬μ©νκ² λ€λ μλ―Έ
@Mock
μ λν
μ΄μ
μ μ¬μ©νμ¬ Mock κ°μ²΄λ‘ λ§λ€ Repository ν΄λμ€ μ§μ ν, νλμ DI
@InjectMocks
μ λν
μ΄μ
μ μ¬μ©νμ¬ Mock κ°μ²΄λ₯Ό μ£Όμ
ν Service ν΄λμ€ μ§μ ν, νλμ DI
ν μ€νΈ μ£Όλ κ°λ°
'ν
μ€νΈλ₯Ό λ¨Όμ νκ³ κ΅¬νμ κ·Έ λ€μμ νλ€'
( ν
μ€νΈ μΌμ΄μ€ λ¨Όμ μμ± ν, κ·Έμ λ§λ μ ν¨μ± κ²μ¦ λ‘μ§μ΄λ νμ©ν λ©μλ / ν΄λμ€λ€μ μμ±νμ¬ failed
ν
μ€νΈ μΌμ΄μ€λ₯Ό passed
λ‘ λ°κΏμ£Όλ κ² )
βοΈ DDD (Domain Driven Design)
λλ©μΈ μ€μ¬μ μ€κ³ κΈ°λ²
[μ°Έκ³ ]
https://www.simform.com/blog/what-is-tdd/
https://ko.wikipedia.org/wiki/%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%A3%BC%EB%8F%84_%EA%B0%9C%EB%B0%9C
λͺ¨λ 쑰건μ λ§μ‘±νλ ν μ€νΈλ₯Ό λ¨Όμ μ§νν λ€, 쑰건μ λ§μ‘±νμ§ μλ ν μ€νΈλ₯Ό λ¨κ³μ μΌλ‘ μ§ννλ©΄μ μ€ν¨νλ ν μ€νΈλ₯Ό μ μ§μ μΌλ‘ μ±κ³΅μμΌ κ°
μ€ν κ²°κ³Όκ° failed
μΈ ν
μ€νΈ μΌμ΄μ€λ₯Ό μ§μμ μΌλ‘ κ·Έλ¦¬κ³ λ¨κ³μ μΌλ‘ μμ νλ©΄μ ν
μ€νΈ μΌμ΄μ€ μ€ν κ²°κ³Όκ° passed
κ° λλλ‘ λ§λ¦
ν
μ€νΈκ° passed
λ λ§νΌμ μ½λλ§ μ°μ μμ±
μ€ν¨νλ ν
μ€νΈ β μ€ν¨νλ ν
μ€νΈλ₯Ό μ±κ³΅ν λ§νΌμ κΈ°λ₯ ꡬν β μ±κ³΅νλ ν
μ€νΈ β 리ν©ν λ§ β μ€ν¨νλ ν
μ€νΈμ μ±κ³΅νλ ν
μ€νΈ νμΈ
μ νλ¦ λ°λ³΅
ν
μ€νΈλ₯Ό ν΅κ³Όν λ§νΌμ κΈ°μ¦μ ꡬν
β νλ²μ λ무 λ§μ κΈ°λ₯ ꡬν νμ X
ν
μ€νΈμ μ½λκ° μΆκ°λλ©΄μ κ²μ¦ λ²μκ° λμ΄μ§ μλ‘, κΈ°λ₯ ꡬνλ μ μ§μ μΌλ‘ μμ±
β λ¨μν κΈ°λ₯ -> 볡μ‘ν κΈ°λ₯μΌλ‘ νμ₯λλ©΄μ κ²μ¦ λΉΌλ¨Ήμ§ μκ³ κ°λ₯
리ν©ν λ§ν λΆλΆμ΄ μκΈ°λ©΄ κ·Έλ κ·Έλ 리ν©ν λ§ κ°λ₯
β 리ν©ν λ§μ λΉμ© μλμ μΌλ‘ μ μ΄μ§
νμ ν μ€νΈ μΌμ΄μ€κ° μ‘΄μ¬νλ―λ‘ μ½λ μμ μ λν μ¬λ¦¬μ λΆμκ°μ΄ μ€μ΄λ¦
리ν©ν λ§μΌλ‘ κΎΈμ€ν μ½λλ₯Ό κ°μ νλ―λ‘ μ½λμ νμ§μ μΌμ λΆλΆ μ μ§ κ°λ₯
μ½λ μμ μ΄ν, λ°λ‘ ν
μ€νΈ κ°λ₯
β μ½λ μμ κ²°κ³Όμ λν λΉ λ₯Έ νΌλλ°±
μμ§ TDD λ°©μμ΄ μ΅μμΉ μλ€λ μ
ν
μ€νΈ μ½λ μμ±μ μ«μ΄νλ μ¬λλ€μκ²λ λΆμ μ μΈ λ°©μ
But, μ€λ¬΄μμλ κ²°κ΅ κΌ ν΄μΌν¨
ν λ¨μλ‘ κ°λ°μ΄ μ§νλλ μ€λ¬΄μμλ νμλ€ κ° μ¬μ νμκ° λμ΄μΌν¨
But, μ΄λ² μ€μ΅μ Mapperλ₯Ό ν μ€νΈ λμμΌλ‘ λ³΄κ³ μμ§ μμ !
μν©μ λ°λΌ Mapperλ 맀νμ΄ μ λλμ§ ν μ€νΈ κ°λ₯ !
......................................................................................................................................................................................................
μλλ path λ‘ urlμ μ§μ ν λ,
mockMvc.perform(get("/v11/members/"+member.getMemberId()));
μ΄λ° μμΌλ‘ μ§μ νμμλλ°
μ μμ μ§μ λ£μ§ μκ³
URI uri = UriComponentsBuilder.newInstance().path("/v11/members").build().toUri();
μμ κ°μ΄ UriComponentsBuilder ν΄λμ€λ₯Ό μ΄μ©νμ¬ μμ±ν΄μ€ μ μλ€ !
μ΄ κ²½μ° pathμλ κ°λ¨ν
mockMvc.perform(get(uri));
μ΄λ κ²λ§ λ£μ΄μ£Όλ©΄ λ°λ‘ μμ± κ°λ₯ !
[μ°Έκ³ ] https://blog.naver.com/PostView.naver?blogId=aservmz&logNo=222322019981
Mockitoκ° λ€μ΄κ°λκΉ μ’ μ΄λ €μμ‘λ€γ
γ
μ¬μ€ νμ΄μ μ€μ΅νλ©΄μ 1μκ° λ°λμ μλ¬λ€μ ν΄κ²°νλλΌ 2κ°μ ν
μ€νΈ μΌμ΄μ€λ°μ μλ£νμ§ λͺ»νλ€.
λμ λ°©μκ³Ό λμ μμ, κ΅¬μ± λ±μ μ μ΅νμ λ€λ₯Έ μ½λλ₯Ό μ°Έκ³ νμ§ μκ³ λ λ°λ‘λ°λ‘ ν
μ€νΈ μΌμ΄μ€λ₯Ό μμ±ν μ μλλ‘ ν΄μΌμ§