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