[Mockito] Strict Stubbing - unnecessary stubbings detected
1.μμ½
λ¨μ ν μ€νΈλ₯Ό μμ±νλ€κ° λ―μ μμΈμ λ§μ£Όμ³€λ€.
ν΄λΉ μμΈ ν΄λμ€μ description μ νμΈν κ²°κ³Ό, mockito νλ μμν¬μ strictness
λ 벨 μ€μ μ κ΄ν μ΄μκ° μμ΄ ν
μ€νΈκ° μ€ν¨νκ³ μμλ€.
strictness μ€μ μ΄λ, μμ
νμλ©΄ λΆνμν stubbing μ νμ©ν μ§ λ§μ§μ λν μ΅μ
μ΄λ€. κΈ°λ³Έ λ λ²¨μ΄ STRICT_STUBS
μ΄λ©°, LENIENT
μΌλ‘ μμ ν΄μ£Όμ΄μΌ μ¬μ©νμ§ μλ stub μ λν΄ λ¬΄μνκ³ ν΅κ³Όν μ μλ€.
μ¦Β stubbing κ΄λ ¨ λ‘μ§μ BeforeEach λ©μλμ λ³λλ‘ μ 리νμλλ° μ΄ mockingμ μ¬μ©νμ§ μλ ν μ€νΈκ° μ‘΄μ¬νμ¬ λ°μνλ μλ¬μλ€.
2.μν©
μλ₯Ό λ€μ΄ νμμ κ΄νμ¬ μ νλ²νΈ μ€λ³΅ μ²΄ν¬ Validation μ μ²λ¦¬νλ μλΉμ€ λ‘μ§μ΄ μκ³ , ν΄λΉ validator λ΄λΆμ Repository ν΄λμ€λ₯Ό mocking νμ¬ λ¨μν μ€νΈλ₯Ό μμ±νλ€κ³ κ°μ ν΄λ³΄μ.
- MemberValidator.java
1
2
3
4
5
6
7
8
9
private final MemberRepository repository;
public void duplicateCheck(SearchCondition cond) {
repository.findOne(cond)
.ifPresent(m -> {
throw new IllegalStateException("Duplicated Memberr");
});
}
- ValidatorTest.java
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
@Mock
MemberRepository repository;
@InjectMocks
MemberValidator validator;
@BeforeEach
void setUp() {
SearchCondition cond = new SearchCondition("01012345678");
SearchCondition wrongCond = new SearchCondition("01056781234");
Member givenMember = Member.builder()
.name("test_member")
.mobile("01012345678")
.build();
doReturn(Optional.of(givenMember)).when(repository).findOne(cond);
doReturn(Optional.empty()).when(repository).findOne(wrongCond);
}
@Test
void notDuplicated() {
Member member = Member.builder()
.mobile("01056781234")
.build();
assertDoesNotThrow(() -> validator.duplicateCheck(member));
}
@Test
void duplicated() {
Member member = Member.builder()
.mobile("01012345678")
.build();
assertThrows(IllegalStateException.class,
() -> validator.duplicateCheck(member));
}
duplicated
ν μ€νΈλcond
κ²μ 쑰건μΌλ‘ stub λ λ°ν κ°μ μ¬μ©νκ³ μλ€.notDuplicated
ν μ€νΈλwrongCond
κ²μ 쑰건μΌλ‘ stub λ λ°ν κ°μ μ¬μ©νκ³ μλ€.
κ·Έλ λ€λ©΄ κ° ν μ€νΈλ μ€ν μ μ¬μ©νμ§ μλ stubbing μ 1νμ© μ€μνκ³ μλ κ²μ΄λ€.
3.ν΄κ²°
μ μν©μ ν΄κ²°ν΄μ£ΌκΈ° μν΄μλ λ€μκ³Ό κ°μ λ°©λ²λ€μ΄ μ‘΄μ¬νλ€.
1) mock strict level μ μ‘°μ νλ€.
1-1. @Mock
μ λ
Έν
μ΄μ
μ lenient κ°μ μ€ μ μλ€.
1
2
3
4
@Mock(lenient = true)
MemberRepository repository;
@InjectMocks
MemberValidator validator;
1-2. stub λ¨μλ³λ‘ lenient() λ©μλ 체μ΄λμ ν΅ν΄ Β lenient λ 벨μ μ‘°μ ν μ μλ€.
1
2
lenient().doReturn(Optional.of(givenMember)).when(repository).findOne(cond);
lenient().doReturn(Optional.empty()).when(repository).findOne(wrongCond);
2) stub μ ν μ€νΈ λ¨μλ³λ‘ μ€μνλ€.
BeforeEach μμμμ 곡μ©μΌλ‘ μ€μνλ stubbing μ ν μ€νΈ λ³ νμν stubbing λ§ μ§ννλλ‘ κ°μ νλ€.
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
@Mock
MemberRepository repository;
@InjectMocks
MemberValidator validator;
@Test
void notDuplicated() {
//given
SearchCondition wrongCond = new SearchCondition("01056781234");
doReturn(Optional.empty()).when(repository).findOne(wrongCond);
//when
Member member = Member.builder()
.mobile("01056781234")
.build();
//then
assertDoesNotThrow(() -> validator.duplicateCheck(member));
}
@Test
void duplicated() {
//given
SearchCondition cond = new SearchCondition("01012345678");
Member givenMember = Member.builder()
.name("test_member")
.mobile("01012345678")
.build();
doReturn(Optional.of(givenMember))
.when(repository).findOne(cond);
//when
Member member = Member.builder()
.mobile("01012345678")
.build();
//then
assertThrows(IllegalStateException.class,
() -> validator.duplicateCheck(member));
}
4.κ²°λ‘
ν μ€νΈ μ½λμ μκ²©μ± (Strictness) λ mockito νλ μμν¬ 2.x λ²μ λΆν° λμ λ κΈ°λ₯μ΄λΌκ³ νλ€. Β μ΄λ ν μ€νΈ μ½λμμ λΆνμν stub λ° μ€λ³΅ μ½λλ₯Ό μ κ±°νκΈ° μν¨μΈλ°, λ³΄ν΅ μ΄λ° κ²½μ° μ΅μ§λ‘ strictness λ 벨μ μ‘°μ νκΈ° λ³΄λ€ νλ μμν¬ μ² νμ λ§μΆμ΄ μ€κ³λ₯Ό μμ νλ νΈμ΄ μ’μ μ½λλ₯Ό μμ±νλ λ°©λ²μ΄ μλκΉ μκ°νλ€.