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