Home | History | Annotate | Download | only in junit
      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