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