1 /* 2 * Copyright (c) 2017 Mockito contributors 3 * This program is made available under the terms of the MIT License. 4 */ 5 package org.mockito.internal.junit; 6 7 import org.mockito.internal.exceptions.Reporter; 8 import org.mockito.internal.listeners.StubbingLookupEvent; 9 import org.mockito.internal.listeners.StubbingLookupListener; 10 import org.mockito.internal.stubbing.UnusedStubbingReporting; 11 import org.mockito.invocation.Invocation; 12 import org.mockito.quality.Strictness; 13 import org.mockito.stubbing.Stubbing; 14 15 import java.util.Collection; 16 import java.util.LinkedList; 17 import java.util.List; 18 19 import static org.mockito.internal.stubbing.StrictnessSelector.determineStrictness; 20 21 /** 22 * Default implementation of stubbing lookup listener. 23 * Fails early if stub called with unexpected arguments, but only if current strictness is set to STRICT_STUBS. 24 */ 25 class DefaultStubbingLookupListener implements StubbingLookupListener { 26 27 private Strictness currentStrictness; 28 private boolean mismatchesReported; 29 30 DefaultStubbingLookupListener(Strictness strictness) { 31 this.currentStrictness = strictness; 32 } 33 34 public void onStubbingLookup(StubbingLookupEvent event) { 35 Strictness actualStrictness = determineStrictness(event.getStubbingFound(), event.getMockSettings(), currentStrictness); 36 37 if (actualStrictness != Strictness.STRICT_STUBS) { 38 return; 39 } 40 41 if (event.getStubbingFound() == null) { 42 //If stubbing was not found for invocation it means that either the mock invocation was not stubbed or 43 //we have a stubbing arg mismatch. 44 List<Invocation> argMismatchStubbings = potentialArgMismatches(event.getInvocation(), event.getAllStubbings()); 45 if (!argMismatchStubbings.isEmpty()) { 46 mismatchesReported = true; 47 Reporter.potentialStubbingProblem(event.getInvocation(), argMismatchStubbings); 48 } 49 } else { 50 //when strict stubs are in use, every time a stub is realized in the code it is implicitly marked as verified 51 //this way, the users don't have to repeat themselves to verify stubbed invocations (DRY) 52 event.getInvocation().markVerified(); 53 } 54 } 55 56 private static List<Invocation> potentialArgMismatches(Invocation invocation, Collection<Stubbing> stubbings) { 57 List<Invocation> matchingStubbings = new LinkedList<Invocation>(); 58 for (Stubbing s : stubbings) { 59 if (UnusedStubbingReporting.shouldBeReported(s) 60 && s.getInvocation().getMethod().getName().equals(invocation.getMethod().getName())) { 61 matchingStubbings.add(s.getInvocation()); 62 } 63 } 64 return matchingStubbings; 65 } 66 67 /** 68 * Enables resetting the strictness to desired level 69 */ 70 void setCurrentStrictness(Strictness currentStrictness) { 71 this.currentStrictness = currentStrictness; 72 } 73 74 /** 75 * Indicates that stubbing argument mismatch was reported 76 */ 77 boolean isMismatchesReported() { 78 return mismatchesReported; 79 } 80 } 81