@ SuppressWarnings ( { "CheckReturnValue" , "MockitoUsage" , "unchecked" } ) static void verifyInt ( MockedVoidMethod method , VerificationMode mode , InOrder instanceInOrder ) { if ( onMethodCallDuringVerification . get ( ) != null ) { throw new IllegalStateException ( "Verification is already in progress on this " + "thread." ) ; } ArrayList < Method > verifications = new ArrayList <> ( ) ; /* Set up callback that is triggered when the next static method is called on this thread. * * This is necessary as we don't know which class the method will be called on. Once the * call is intercepted this will * 1. Remove all matchers (e.g. eq(), any()) from the matcher stack * 2. Call verify on the marker for the class * 3. Add the markers back to the stack */ onMethodCallDuringVerification . set ( ( clazz , verifiedMethod ) -> { // TODO: O holy reflection! Let's hope we can integrate this better. try { ArgumentMatcherStorageImpl argMatcherStorage = ( ArgumentMatcherStorageImpl ) mockingProgress ( ) . getArgumentMatcherStorage ( ) ; List < LocalizedMatcher > matchers ; // Matcher are called before verify, hence remove the from the storage Method resetStackMethod = argMatcherStorage . getClass ( ) . getDeclaredMethod ( "resetStack" ) ; resetStackMethod . setAccessible ( true ) ; matchers = ( List < LocalizedMatcher > ) resetStackMethod . invoke ( argMatcherStorage ) ; if ( instanceInOrder == null ) { verify ( staticMockMarker ( clazz ) , mode ) ; } else { instanceInOrder . verify ( staticMockMarker ( clazz ) , mode ) ; } // Add the matchers back after verify is called Field matcherStackField = argMatcherStorage . getClass ( ) . getDeclaredField ( "matcherStack" ) ; matcherStackField . setAccessible ( true ) ; Method pushMethod = matcherStackField . getType ( ) . getDeclaredMethod ( "push" , Object . class ) ; for ( LocalizedMatcher matcher : matchers ) { pushMethod . invoke ( matcherStackField . get ( argMatcherStorage ) , matcher ) ; } } catch ( NoSuchFieldException | NoSuchMethodException | IllegalAccessException | InvocationTargetException | ClassCastException e ) { throw new Error ( "Reflection failed. Do you use a compatible version of " + "mockito?" , e ) ; } verifications . add ( verifiedMethod ) ; } ) ; try { try { // Trigger the method call. This call will be intercepted and trigger the // onMethodCallDuringVerification callback. method . run ( ) ; } catch ( Throwable t ) { if ( t instanceof RuntimeException ) { throw ( RuntimeException ) t ; } else if ( t instanceof Error ) { throw ( Error ) t ; } throw new RuntimeException ( t ) ; } if ( verifications . isEmpty ( ) ) { // Make sure something was intercepted throw new IllegalArgumentException ( "Nothing was verified. Does the lambda call " + "a static method on a 'static' mock/spy ?" ) ; } else if ( verifications . size ( ) > 1 ) { // A lambda might call several methods. In this case it is not clear what should // be verified. Hence throw an error. throw new IllegalArgumentException ( "Multiple intercepted calls on methods " + verifications ) ; } } finally { onMethodCallDuringVerification . remove ( ) ; } }
Common implementation of verification of static method calls .