|
5 | 5 | package org.mockitousage.junitrule; |
6 | 6 |
|
7 | 7 | import static org.junit.Assert.assertEquals; |
| 8 | +import static org.mockito.ArgumentMatchers.argThat; |
| 9 | +import static org.mockito.ArgumentMatchers.eq; |
8 | 10 | import static org.mockito.BDDMockito.given; |
9 | 11 | import static org.mockito.BDDMockito.willReturn; |
10 | 12 | import static org.mockito.Mockito.verify; |
@@ -102,9 +104,9 @@ public void doAssert(Throwable t) { |
102 | 104 | + " mock.simpleMethod(15);\n" |
103 | 105 | + " -> at org.mockitousage.strictness.ProductionCode.simpleMethod(ProductionCode.java:0)\n" |
104 | 106 | + " - has following stubbing(s) with different arguments:\n" |
105 | | - + " 1. mock.simpleMethod(20);\n" |
| 107 | + + " 1. mock.simpleMethod(20); stubbed with: [Returns: 20]\n" |
106 | 108 | + " -> at org.mockitousage.junitrule.StrictJUnitRuleTest.fails_fast_when_stubbing_invoked_with_different_argument(StrictJUnitRuleTest.java:0)\n" |
107 | | - + " 2. mock.simpleMethod(30);\n" |
| 109 | + + " 2. mock.simpleMethod(30); stubbed with: [Returns: 30]\n" |
108 | 110 | + " -> at org.mockitousage.junitrule.StrictJUnitRuleTest.fails_fast_when_stubbing_invoked_with_different_argument(StrictJUnitRuleTest.java:0)\n" |
109 | 111 | + "Typically, stubbing argument mismatch indicates user mistake when writing tests.\n" |
110 | 112 | + "Mockito fails early so that you can debug potential problem easily.\n" |
@@ -132,6 +134,101 @@ public void doAssert(Throwable t) { |
132 | 134 | ProductionCode.simpleMethod(mock, 15); |
133 | 135 | } |
134 | 136 |
|
| 137 | + @Test |
| 138 | + public void fails_fast_when_stubbing_invoked_with_different_argument_using_matchers() |
| 139 | + throws Throwable { |
| 140 | + // expect |
| 141 | + rule.expectFailure( |
| 142 | + new SafeJUnitRule.FailureAssert() { |
| 143 | + public void doAssert(Throwable t) { |
| 144 | + Assertions.assertThat(t).isInstanceOf(PotentialStubbingProblem.class); |
| 145 | + assertEquals( |
| 146 | + filterLineNo( |
| 147 | + "\n" |
| 148 | + + "Strict stubbing argument mismatch. Please check:\n" |
| 149 | + + " - this invocation of 'simpleMethod' method:\n" |
| 150 | + + " mock.simpleMethod(15);\n" |
| 151 | + + " -> at org.mockitousage.strictness.ProductionCode.simpleMethod(ProductionCode.java:0)\n" |
| 152 | + + " - has following stubbing(s) with different arguments:\n" |
| 153 | + + " 1. mock.simpleMethod(20); stubbed with: [Returns: 20]\n" |
| 154 | + + " -> at org.mockitousage.junitrule.StrictJUnitRuleTest.fails_fast_when_stubbing_invoked_with_different_argument_using_matchers(StrictJUnitRuleTest.java:0)\n" |
| 155 | + + " 2. mock.simpleMethod(30); stubbed with: [Returns: 30]\n" |
| 156 | + + " -> at org.mockitousage.junitrule.StrictJUnitRuleTest.fails_fast_when_stubbing_invoked_with_different_argument_using_matchers(StrictJUnitRuleTest.java:0)\n" |
| 157 | + + " 3. mock.simpleMethod(\"40\"); stubbed with: [Returns: 40]\n" |
| 158 | + + " -> at org.mockitousage.junitrule.StrictJUnitRuleTest.fails_fast_when_stubbing_invoked_with_different_argument_using_matchers(StrictJUnitRuleTest.java:0)\n" |
| 159 | + + "Typically, stubbing argument mismatch indicates user mistake when writing tests.\n" |
| 160 | + + "Mockito fails early so that you can debug potential problem easily.\n" |
| 161 | + + "However, there are legit scenarios when this exception generates false negative signal:\n" |
| 162 | + + " - stubbing the same method multiple times using 'given().will()' or 'when().then()' API\n" |
| 163 | + + " Please use 'will().given()' or 'doReturn().when()' API for stubbing.\n" |
| 164 | + + " - stubbed method is intentionally invoked with different arguments by code under test\n" |
| 165 | + + " Please use default or 'silent' JUnit Rule (equivalent of Strictness.LENIENT).\n" |
| 166 | + + "For more information see javadoc for PotentialStubbingProblem class."), |
| 167 | + filterLineNo(t.getMessage())); |
| 168 | + } |
| 169 | + }); |
| 170 | + |
| 171 | + // when stubbings in the test code: |
| 172 | + willReturn("10").given(mock).simpleMethod(eq(10)); // used |
| 173 | + willReturn("20").given(mock).simpleMethod(eq(20)); // unused |
| 174 | + willReturn("30").given(mock).simpleMethod(eq(30)); // unused |
| 175 | + willReturn("40").given(mock).simpleMethod(eq("40")); // unused |
| 176 | + |
| 177 | + // then |
| 178 | + mock.otherMethod(); // ok, different method |
| 179 | + mock.simpleMethod(10); // ok, stubbed with this argument |
| 180 | + |
| 181 | + // invocation in the code under test uses different argument and should fail immediately |
| 182 | + // this helps with debugging and is essential for Mockito strictness |
| 183 | + ProductionCode.simpleMethod(mock, 15); |
| 184 | + } |
| 185 | + |
| 186 | + @Test |
| 187 | + public void fails_fast_when_stubbing_invoked_with_different_argument_using_argThat_matcher() |
| 188 | + throws Throwable { |
| 189 | + // expect |
| 190 | + rule.expectFailure( |
| 191 | + new SafeJUnitRule.FailureAssert() { |
| 192 | + public void doAssert(Throwable t) { |
| 193 | + Assertions.assertThat(t).isInstanceOf(PotentialStubbingProblem.class); |
| 194 | + assertEquals( |
| 195 | + filterLineNo( |
| 196 | + "\n" |
| 197 | + + "Strict stubbing argument mismatch. Please check:\n" |
| 198 | + + " - this invocation of 'forInteger' method:\n" |
| 199 | + + " mock.forInteger(15);\n" |
| 200 | + + " -> at org.mockitousage.strictness.ProductionCode.forInteger(ProductionCode.java:0)\n" |
| 201 | + + " - has following stubbing(s) with different arguments:\n" |
| 202 | + + " 1. mock.forInteger(<custom argument matcher>); stubbed with: [Returns: 20]\n" |
| 203 | + + " -> at org.mockitousage.junitrule.StrictJUnitRuleTest.fails_fast_when_stubbing_invoked_with_different_argument_using_argThat_matcher(StrictJUnitRuleTest.java:0)\n" |
| 204 | + + " 2. mock.forInteger(<custom argument matcher>); stubbed with: [Returns: 30]\n" |
| 205 | + + " -> at org.mockitousage.junitrule.StrictJUnitRuleTest.fails_fast_when_stubbing_invoked_with_different_argument_using_argThat_matcher(StrictJUnitRuleTest.java:0)\n" |
| 206 | + + "Typically, stubbing argument mismatch indicates user mistake when writing tests.\n" |
| 207 | + + "Mockito fails early so that you can debug potential problem easily.\n" |
| 208 | + + "However, there are legit scenarios when this exception generates false negative signal:\n" |
| 209 | + + " - stubbing the same method multiple times using 'given().will()' or 'when().then()' API\n" |
| 210 | + + " Please use 'will().given()' or 'doReturn().when()' API for stubbing.\n" |
| 211 | + + " - stubbed method is intentionally invoked with different arguments by code under test\n" |
| 212 | + + " Please use default or 'silent' JUnit Rule (equivalent of Strictness.LENIENT).\n" |
| 213 | + + "For more information see javadoc for PotentialStubbingProblem class."), |
| 214 | + filterLineNo(t.getMessage())); |
| 215 | + } |
| 216 | + }); |
| 217 | + |
| 218 | + // when stubbings in the test code: |
| 219 | + willReturn("10").given(mock).forInteger(argThat(x -> x < 11)); // used |
| 220 | + willReturn("20").given(mock).forInteger(argThat(x -> x > 19)); // unused |
| 221 | + willReturn("30").given(mock).forInteger(argThat(x -> x > 29)); // unused |
| 222 | + |
| 223 | + // then |
| 224 | + mock.otherMethod(); // ok, different method |
| 225 | + mock.forInteger(10); // ok, stubbed with this argument |
| 226 | + |
| 227 | + // invocation in the code under test uses different argument and should fail immediately |
| 228 | + // this helps with debugging and is essential for Mockito strictness |
| 229 | + ProductionCode.forInteger(mock, 15); |
| 230 | + } |
| 231 | + |
135 | 232 | @Test |
136 | 233 | public void verify_no_more_interactions_ignores_stubs() throws Throwable { |
137 | 234 | // when stubbing in test: |
|
0 commit comments