• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.mockitousage.junitrule;
2 
3 import org.assertj.core.api.Assertions;
4 import org.junit.Rule;
5 import org.junit.Test;
6 import org.mockito.Mock;
7 import org.mockito.quality.Strictness;
8 import org.mockito.exceptions.misusing.PotentialStubbingProblem;
9 import org.mockito.exceptions.misusing.UnfinishedVerificationException;
10 import org.mockito.exceptions.misusing.UnnecessaryStubbingException;
11 import org.mockito.junit.MockitoJUnit;
12 import org.mockitousage.IMethods;
13 import org.mockitoutil.SafeJUnitRule;
14 
15 import static org.junit.Assert.assertEquals;
16 import static org.mockito.BDDMockito.given;
17 import static org.mockito.BDDMockito.willReturn;
18 import static org.mockito.Mockito.*;
19 import static org.mockitoutil.TestBase.filterLineNo;
20 
21 public class StrictJUnitRuleTest {
22 
23     @Rule public SafeJUnitRule rule = new SafeJUnitRule(MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS));
24 
25     @Mock IMethods mock;
26     @Mock IMethods mock2;
27 
ok_when_no_stubbings()28     @Test public void ok_when_no_stubbings() throws Throwable {
29         mock.simpleMethod();
30         verify(mock).simpleMethod();
31     }
32 
ok_when_all_stubbings_used()33     @Test public void ok_when_all_stubbings_used() throws Throwable {
34         given(mock.simpleMethod(10)).willReturn("foo");
35         mock.simpleMethod(10);
36     }
37 
ok_when_used_and_mismatched_argument()38     @Test public void ok_when_used_and_mismatched_argument() throws Throwable {
39         given(mock.simpleMethod(10)).willReturn("foo");
40         mock.simpleMethod(10);
41         mock.simpleMethod(15);
42     }
43 
fails_when_unused_stubbings()44     @Test public void fails_when_unused_stubbings() throws Throwable {
45         //expect
46         rule.expectFailure(UnnecessaryStubbingException.class);
47 
48         //when
49         given(mock.simpleMethod(10)).willReturn("foo");
50         mock2.simpleMethod(10);
51     }
52 
test_failure_trumps_unused_stubbings()53     @Test public void test_failure_trumps_unused_stubbings() throws Throwable {
54         //expect
55         rule.expectFailure(AssertionError.class, "x");
56 
57         //when
58         given(mock.simpleMethod(10)).willReturn("foo");
59         mock.otherMethod();
60 
61         throw new AssertionError("x");
62     }
63 
why_do_return_syntax_is_useful()64     @Test public void why_do_return_syntax_is_useful() throws Throwable {
65         //Trade-off of Mockito strictness documented in test
66 
67         //expect
68         rule.expectFailure(PotentialStubbingProblem.class);
69 
70         //when
71         when(mock.simpleMethod(10)).thenReturn("10");
72         when(mock.simpleMethod(20)).thenReturn("20");
73     }
74 
fails_fast_when_stubbing_invoked_with_different_argument()75     @Test public void fails_fast_when_stubbing_invoked_with_different_argument() throws Throwable {
76         //expect
77         rule.expectFailure(new SafeJUnitRule.FailureAssert() {
78             public void doAssert(Throwable t) {
79                 Assertions.assertThat(t).isInstanceOf(PotentialStubbingProblem.class);
80                 assertEquals(filterLineNo("\n" +
81                                 "Strict stubbing argument mismatch. Please check:\n" +
82                                 " - this invocation of 'simpleMethod' method:\n" +
83                                 "    mock.simpleMethod(15);\n" +
84                                 "    -> at org.mockitousage.junitrule.StrictJUnitRuleTest.fails_fast_when_stubbing_invoked_with_different_argument(StrictJUnitRuleTest.java:0)\n" +
85                                 " - has following stubbing(s) with different arguments:\n" +
86                                 "    1. mock.simpleMethod(20);\n" +
87                                 "      -> at org.mockitousage.junitrule.StrictJUnitRuleTest.fails_fast_when_stubbing_invoked_with_different_argument(StrictJUnitRuleTest.java:0)\n" +
88                                 "    2. mock.simpleMethod(30);\n" +
89                                 "      -> at org.mockitousage.junitrule.StrictJUnitRuleTest.fails_fast_when_stubbing_invoked_with_different_argument(StrictJUnitRuleTest.java:0)\n" +
90                                 "Typically, stubbing argument mismatch indicates user mistake when writing tests.\n" +
91                                 "Mockito fails early so that you can debug potential problem easily.\n" +
92                                 "However, there are legit scenarios when this exception generates false negative signal:\n" +
93                                 "  - stubbing the same method multiple times using 'given().will()' or 'when().then()' API\n" +
94                                 "    Please use 'will().given()' or 'doReturn().when()' API for stubbing.\n" +
95                                 "  - stubbed method is intentionally invoked with different arguments by code under test\n" +
96                                 "    Please use 'default' or 'silent' JUnit Rule.\n" +
97                                 "For more information see javadoc for PotentialStubbingProblem class."),
98                         filterLineNo(t.getMessage()));
99             }
100         });
101 
102         //when stubbings in the test code:
103         willReturn("10").given(mock).simpleMethod(10) ;  //used
104         willReturn("20").given(mock).simpleMethod(20) ;  //unused
105         willReturn("30").given(mock).simpleMethod(30) ;  //unused
106 
107         //then
108         mock.otherMethod(); //ok, different method
109         mock.simpleMethod(10); //ok, stubbed with this argument
110 
111         //invocation in the code under test uses different argument and should fail immediately
112         //this helps with debugging and is essential for Mockito strictness
113         mock.simpleMethod(15);
114     }
115 
verify_no_more_interactions_ignores_stubs()116     @Test public void verify_no_more_interactions_ignores_stubs() throws Throwable {
117         //when stubbing in test:
118         given(mock.simpleMethod(10)).willReturn("foo");
119 
120         //and code under test does:
121         mock.simpleMethod(10); //implicitly verifies the stubbing
122         mock.otherMethod();
123 
124         //and in test we:
125         verify(mock).otherMethod();
126         verifyNoMoreInteractions(mock);
127     }
128 
unused_stubs_with_multiple_mocks()129     @Test public void unused_stubs_with_multiple_mocks() throws Throwable {
130         //expect
131         rule.expectFailure(new SafeJUnitRule.FailureAssert() {
132             public void doAssert(Throwable t) {
133                 assertEquals(filterLineNo("\n" +
134                         "Unnecessary stubbings detected.\n" +
135                         "Clean & maintainable test code requires zero unnecessary code.\n" +
136                         "Following stubbings are unnecessary (click to navigate to relevant line of code):\n" +
137                         "  1. -> at org.mockitousage.junitrule.StrictJUnitRuleTest.unused_stubs_with_multiple_mocks(StrictJUnitRuleTest.java:0)\n" +
138                         "  2. -> at org.mockitousage.junitrule.StrictJUnitRuleTest.unused_stubs_with_multiple_mocks(StrictJUnitRuleTest.java:0)\n" +
139                         "Please remove unnecessary stubbings or use 'silent' option. More info: javadoc for UnnecessaryStubbingException class."), filterLineNo(t.getMessage()));
140             }
141         });
142 
143         //when test has
144         given(mock.simpleMethod(10)).willReturn("foo");
145         given(mock2.simpleMethod(20)).willReturn("foo");
146 
147         given(mock.otherMethod()).willReturn("foo"); //used and should not be reported
148 
149         //and code has
150         mock.otherMethod();
151         mock2.booleanObjectReturningMethod();
152     }
153 
rule_validates_mockito_usage()154     @Test public void rule_validates_mockito_usage() throws Throwable {
155         //expect
156         rule.expectFailure(UnfinishedVerificationException.class);
157 
158         //when test contains unfinished verification
159         verify(mock);
160     }
161 }
162