我是靠谱客的博主 老迟到冬日,最近开发中收集的这篇文章主要介绍Mockito详细介绍简介使用原理参考,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

文章目录

  • 简介
    • mock、stub、spy
  • 使用
    • 引入
    • 代码
  • 原理
    • 框架设计
    • mock
        • 创建MockHandler
        • 创建mock对象
    • when
        • OngoingStubbing
    • verify
    • Handler
    • MockingProgress
    • 匹配器
      • ArgumentCaptor
      • CapturingMatcher
  • 参考
    • bytebuddy
    • Mockito生成的Class
      • Class说明
      • MockMethodInterceptor

简介

测试驱动的开发(Test Driven Design, TDD)要求我们先写单元测试,再写实现代码。在写单元测试的过程中,一个很普遍的问题是,要测试的类会有很多依赖,这些依赖的类/对象/资源又会有别的依赖,从而形成一个大的依赖树,要在单元测试的环境中完整地构建这样的依赖,是一件很困难的事情。

所幸,我们有一个应对这个问题的办法:Mock。简单地说就是对测试的类所依赖的其他类和对象,进行mock - 构建它们的一个假的对象,定义这些假对象上的行为,然后提供给被测试对象使用。被测试对象像使用真的对象一样使用它们。用这种方式,我们可以把测试的目标限定于被测试对象本身,就如同在被测试对象周围做了一个划断,形成了一个尽量小的被测试目标。Mock的框架有很多,最为知名的一个是Mockito,这是一个开源项目,使用广泛。

mock、stub、spy

mock是构造假对象。stub也就是常说的打桩,针对某些入参返回自定义数据,即把调用返回值进行绑定。;mock也就是mock类,默认返回空数据(一般是null)。

spy对真实对象进行监控。

使用

引入

        <!--测试依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <version>2.2.2.RELEASE</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.mockito/mockito-core -->
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-core</artifactId>
            <version>2.7.22</version>
            <scope>test</scope>
        </dependency>

代码

原理

2.7.22的源码。

框架设计

Mock对象这件事情,本质上是一个Proxy模式的应用。Proxy模式说的是,在一个真实对象前面,提供一个proxy对象,所有对真实对象的调用,都先经过proxy对象,然后由proxy对象根据情况,决定相应的处理,它可以直接做一个自己的处理,也可以再调用真实对象对应的方法。

Java本身提供了构建Proxy对象的API:Java Dynamic Proxy API,而Mockito是用**Cglib**来实现的。

Mokito利用Cglib为Mock的接口的所有方法都做了Mock实现。所有的方法调用都经过了proxy对象,proxy对象可以记录所有调用的信息,供验证的时候去检查。当when()方法被调用时,调用proxy的对应的方法,返回的不是某个值,而是方法调用的信息(invocationMatcher 对象),在调用thenReturn()方法时,把调用信息返回值进行了绑定。则后面调用时,会根据调用信息(invocationMatcher 对象),找到绑定的值,直接返回。

public interface InvocationListener {
    void reportInvocation(MethodInvocationReport methodInvocationReport);
}

public interface MethodInvocationReport {
    DescribedInvocation getInvocation();
    Object getReturnedValue();
    Throwable getThrowable();
    boolean threwException();
    String getLocationOfStubbing();
}

public class NotifiedMethodInvocationReport implements MethodInvocationReport {
    private final Invocation invocation;
    private final Object returnedValue;
    private final Throwable throwable;
}

mock

Mockito类中有几个mock函数的重载,最终都会调到mock(Class<T> classToMock, MockSettings mockSettings),接受一个class类型与一个mockSettings,class就是我们需要mock对象的类型,而mockSettings则记录着此次mock的一些信息。mock的行为实则转交个MockitoCore

MOCKITO_CORE.mock(classToMock, mockSettings)
   //===MockitoCore 
   public <T> T mock(Class<T> typeToMock, MockSettings settings) {
        if (!MockSettingsImpl.class.isInstance(settings)) {
            throw new IllegalArgumentException("Unexpected implementation of '" + settings.getClass().getCanonicalName() + "'n" + "At the moment, you cannot provide your own implementations of that class.");
        }
        MockSettingsImpl impl = MockSettingsImpl.class.cast(settings);
        MockCreationSettings<T> creationSettings = impl.confirm(typeToMock);
        //MockUtil的createMock方法
        T mock = createMock(creationSettings);
        mockingProgress().mockingStarted(mock, creationSettings);
        return mock;
    }

MockUtil中则作了两件非常关键的事情:

    //===MockUtil
	public static <T> T createMock(MockCreationSettings<T> settings) {
    //创建MockHandler
        MockHandler mockHandler =  createMockHandler(settings);
   //MOCK
        T mock = mockMaker.createMock(settings, mockHandler);

        Object spiedInstance = settings.getSpiedInstance();
        if (spiedInstance != null) {
            new LenientCopyTool().copyToMock(spiedInstance, mock);
        }

        return mock;
    }

创建MockHandler

MockHandler对象的实例是InvocationNotifierHandler类型,但它只是负责对外的包装,内部实际起作用的是MockHandlerImpl,承载了Mockito的主要逻辑。InvocationNotifierHandler 主要提供了事件通知功能。

public class MockHandlerFactory {

    public static <T> InternalMockHandler<T> createMockHandler(MockCreationSettings<T> settings) {
        //内部Handler是MockHandlerImpl
        InternalMockHandler<T> handler = new MockHandlerImpl<T>(settings);
        //nullResultGuardian是个代理类,用于处理返回值为null或者原生类型的情况。
        InternalMockHandler<T> nullResultGuardian = new NullResultGuardian<T>(handler);
        
        return new InvocationNotifierHandler<T>(nullResultGuardian, settings);
    }
}
class InvocationNotifierHandler<T> implements MockHandler, InternalMockHandler<T> {

    private final List<InvocationListener> invocationListeners;
    private final InternalMockHandler<T> mockHandler;
    
    public Object handle(Invocation invocation) throws Throwable {
        try {
            Object returnedValue = mockHandler.handle(invocation);
            //通知:调用事件。
            notifyMethodCall(invocation, returnedValue);
            return returnedValue;
        } catch (Throwable t){
            notifyMethodCallException(invocation, t);
            throw t;
        }
    }


    private void notifyMethodCall(Invocation invocation, Object returnValue) {
        for (InvocationListener listener : invocationListeners) {
            try {
                listener.reportInvocation(new NotifiedMethodInvocationReport(invocation, returnValue));
            } catch(Throwable listenerThrowable) {
                throw invocationListenerThrewException(listener, listenerThrowable);
            }
        }
    }

创建mock对象

创建mock对象使用MockMakerMockMaker是个接口,用于创建mock对象,通过插件注册机制发现MockMaker实例。

private static final MockMaker mockMaker = Plugins.getMockMaker();

MockMaker有以下几个子类

  • ClassCreatingMockMaker:接口,通过生成类创建Mock对象
  • ByteBuddyMockMaker:内部使用SubclassByteBuddyMockMaker 构造mock Class。
  • SubclassByteBuddyMockMaker:通过子类方式构造Class。
  • InlineByteBuddyMockMaker:使用Java instrumentation API mock Class。
public interface MockMaker {
    <T> T createMock(
            MockCreationSettings<T> settings,
            MockHandler handler
    );
    MockHandler getHandler(Object mock);
    void resetMock(
            Object mock,
            MockHandler newHandler,
            MockCreationSettings settings
    );
    @Incubating
    TypeMockability isTypeMockable(Class<?> type);

    @Incubating
    interface TypeMockability {
        boolean mockable();
        String nonMockableReason();
    }
}

interface ClassCreatingMockMaker extends MockMaker {
    <T> Class<? extends T> createMockType(MockCreationSettings<T> settings);
}

//=== SubclassByteBuddyMockMaker
public <T> T createMock(MockCreationSettings<T> settings, MockHandler handler){
    //构造代理类型(生成一个class),通过byte buddy构造Class。
    Class<T> mockedProxyType = createProxyClass(mockWithFeaturesFrom(settings));
    Instantiator instantiator = Plugins.getInstantiatorProvider().getInstantiator(settings);
    T mockInstance = null;
    //实例化代理类型。
    mockInstance = instantiator.newInstance(mockedProxyType);
    MockAccess mockAccess = (MockAccess) mockInstance;
    mockAccess.setMockitoInterceptor(new MockMethodInterceptor(asInternalMockHandler(handler), settings));
    return ensureMockIsAssignableToMockedType(settings, mockInstance);
}

这个Instantiator也是一个接口,它有两个实现,一是ObjenesisInstantiator,另外一个是ConstructorInstantiator, 默认情况下,都是在使用 ObjenesisInstantiator

objenesis是一个框架,可以根据不同的平台选 择不同的方法来new对象。

when

    //=== Mockito
    public static <T> OngoingStubbing<T> when(T methodCall) {
        return MOCKITO_CORE.when(methodCall);
    }
    //MOCKITO_CORE
    public <T> OngoingStubbing<T> when(T methodCall) {
        MockingProgress mockingProgress = mockingProgress();
        mockingProgress.stubbingStarted();
        @SuppressWarnings("unchecked")
        OngoingStubbing<T> stubbing = (OngoingStubbing<T>) mockingProgress.pullOngoingStubbing();
        if (stubbing == null) {
            mockingProgress.reset();
            throw missingMethodInvocation();
        }
        return stubbing;
    }

OngoingStubbing

OngoingStubbing接口封装了stub,用于保存调用对应的返回值以及异常。

public interface OngoingStubbing<T> {
    //设置返回值
    OngoingStubbing<T> thenReturn(T value);

    //设置连续返回的返回值。一次调用返回一个值。
    // Additional method helps users of JDK7+ to hide heap pollution / unchecked generics array creation warnings (on call site)
    @SuppressWarnings ({"unchecked", "varargs"})
    OngoingStubbing<T> thenReturn(T value, T... values);

    OngoingStubbing<T> thenThrow(Throwable... throwables);
    OngoingStubbing<T> thenThrow(Class<? extends Throwable> throwableType);
    // Additional method helps users of JDK7+ to hide heap pollution / unchecked generics array creation warnings (on call site)
    @SuppressWarnings ({"unchecked", "varargs"})
    OngoingStubbing<T> thenThrow(Class<? extends Throwable> toBeThrown, Class<? extends Throwable>... nextToBeThrown);

    OngoingStubbing<T> thenCallRealMethod();
    OngoingStubbing<T> thenAnswer(Answer<?> answer);
    OngoingStubbing<T> then(Answer<?> answer);
    
    <M> M getMock();
}

verify

verify的基本使用形式是verify(mock).doSome(),verify有几个重载函数,但最终都会掉到如下函数:

    //MOCKITO_CORE
    public <T> T verify(T mock, VerificationMode mode) {
        if (mock == null) {
            throw nullPassedToVerify();
        }
        if (!isMock(mock)) {
            throw notAMockPassedToVerify(mock.getClass());
        }
        MockingProgress mockingProgress = mockingProgress();
        VerificationMode actualMode = mockingProgress.maybeVerifyLazily(mode);
        mockingProgress.verificationStarted(new MockAwareVerificationMode(mock, actualMode, mockingProgress.verificationListeners()));
        return mock;
    }

VerificationMode是对验证信息的封装,它是一个接口,含有verify函数。常用的never(). times(1)返回的都是Times类型,而Times类型就是VerificationMode的一种实现。

public interface VerificationMode {
    void verify(VerificationData data);
    VerificationMode description(String description);
}

通过以下静态方法,可以构造VerificationMode

  • atLeastOnce:至少进行一次验证
  • atLeast:允许至少进行x次验证
  • only
  • times
  • calls:允许顺序进行non-greedy验证
  • noMoreInteractions
  • atMost:至多进行x次验证
  • description

Handler

mockito对接口进行mock,针对mock对象的每个方法都生成了代码,最终调用MockHandlerImplhandle()方法。handler保存了MockSettingsImpl实例。MockSettingsImpl实例保存了mock对象的所有配置信息,包括接口信息,spy信息,stub等。

public interface MockHandler extends Serializable {
    Object handle(Invocation invocation) throws Throwable;
}

public interface InternalMockHandler<T> extends MockHandler {
    MockCreationSettings<T> getMockSettings();
    void setAnswersForStubbing(List<Answer<?>> answers);
    InvocationContainer getInvocationContainer();
}

public class MockHandlerImpl<T> implements InternalMockHandler<T> {

    private static final long serialVersionUID = -2917871070982574165L;
	//调用容器
    InvocationContainerImpl invocationContainerImpl;
	//匹配器
    MatchersBinder matchersBinder = new MatchersBinder();
	//mock 设置信息
    private final MockCreationSettings<T> mockSettings;
}

Handler处理逻辑:


    public Object handle(Invocation invocation) throws Throwable {
        //是否有Answer,如果有,则由Answer处理。
        if (invocationContainerImpl.hasAnswersForStubbing()) {
            // stubbing voids with doThrow() or doAnswer() style
            InvocationMatcher invocationMatcher = matchersBinder.bindMatchers(
                    mockingProgress().getArgumentMatcherStorage(),
                    invocation
            );
            invocationContainerImpl.setMethodForStubbing(invocationMatcher);
            return null;
        }
        //Verify逻辑处理。获取验证模式。
        VerificationMode verificationMode = mockingProgress().pullVerificationMode();

        InvocationMatcher invocationMatcher = matchersBinder.bindMatchers(
                mockingProgress().getArgumentMatcherStorage(),
                invocation
        );
		
        mockingProgress().validateState();

        //verificationMode不为null,表示正在进行verify操作。
        if (verificationMode != null) {
            // We need to check if verification was started on the correct mock
            // - see VerifyingWithAnExtraCallToADifferentMockTest (bug 138)
            //同一个mock对象,则验证
            if (((MockAwareVerificationMode) verificationMode).getMock() == invocation.getMock()) {
                VerificationDataImpl data = createVerificationData(invocationContainerImpl, invocationMatcher);
                //验证
                verificationMode.verify(data);
                return null;
            } else {
                //否则开始验证。
                // this means there is an invocation on a different mock. Re-adding verification mode
                // - see VerifyingWithAnExtraCallToADifferentMockTest (bug 138)
                mockingProgress().verificationStarted(verificationMode);
            }
        }

        // stub处理逻辑。
        invocationContainerImpl.setInvocationForPotentialStubbing(invocationMatcher);
        OngoingStubbingImpl<T> ongoingStubbing = new OngoingStubbingImpl<T>(invocationContainerImpl);
        mockingProgress().reportOngoingStubbing(ongoingStubbing);

        // look for existing answer for this invocation
        StubbedInvocationMatcher stubbedInvocation = invocationContainerImpl.findAnswerFor(invocation);
        notifyStubbedAnswerLookup(invocation, stubbedInvocation);

        if (stubbedInvocation != null) {
            stubbedInvocation.captureArgumentsFrom(invocation);
            return stubbedInvocation.answer(invocation);
        } else {
            Object ret = mockSettings.getDefaultAnswer().answer(invocation);
            DefaultAnswerValidator.validateReturnValueFor(invocation, ret);

            //====局部 mock,spy 处理逻辑
            // redo setting invocation for potential stubbing in case of partial
            // mocks / spies.
            // Without it, the real method inside 'when' might have delegated
            // to other self method and overwrite the intended stubbed method
            // with a different one. The reset is required to avoid runtime exception that validates return type with stubbed method signature.
            invocationContainerImpl.resetInvocationForPotentialStubbing(invocationMatcher);
            return ret;
        }
    }

MockingProgress

MockingProgress用于控制mock的处理过程。通过ThreadLocal多线程并发控制。内部实现为MockingProgressImpl。 当when和verify时,通过获取ThreadLocal获取到线程中的MockingProgress实例。

public class ThreadSafeMockingProgress {
    private static final ThreadLocal<MockingProgress> MOCKING_PROGRESS_PROVIDER = new ThreadLocal<MockingProgress>() {
        @Override
        protected MockingProgress initialValue() {
            return new MockingProgressImpl();
        }
    };

    private ThreadSafeMockingProgress() {
    }

    public final static MockingProgress mockingProgress() {
        return MOCKING_PROGRESS_PROVIDER.get();
    }
}
public class MockingProgressImpl implements MockingProgress {
	//参数匹配器存储
    private final ArgumentMatcherStorage argumentMatcherStorage = new ArgumentMatcherStorageImpl();
	//stub,when调用时设置。report时重新设置。
    private OngoingStubbing<?> ongoingStubbing;
    //验证模式。verify调用时设置。
    private Localized<VerificationMode> verificationMode;
    //进度:返回string。默认实现:LocationImpl
    private Location stubbingInProgress = null;
    //验证策略。默认直接返回参数
    private VerificationStrategy verificationStrategy;
    //listeners。mock 调用时设置。verify时从此复制。
    private final Set<MockitoListener> listeners = new LinkedHashSet<MockitoListener>();
}

mock调用

    public void mockingStarted(Object mock, MockCreationSettings settings) {
        //通知事件。
        for (MockitoListener listener : listeners) {
            if (listener instanceof MockCreationListener) {
                ((MockCreationListener) listener).onMockCreated(mock, settings);
            }
        }
        //校验成员
        validateMostStuff();
    }

when调用

    public void stubbingStarted() {
        validateState();
        //设置初始进度
        stubbingInProgress = new LocationImpl();
    }
    public void validateState() {
        validateMostStuff();

        //validate stubbing:
        if (stubbingInProgress != null) {
            Location temp = stubbingInProgress;
            stubbingInProgress = null;
            throw unfinishedStubbing(temp);
        }
    }
   private void validateMostStuff() {
        //State is cool when GlobalConfiguration is already loaded
        //this cannot really be tested functionally because I cannot dynamically mess up org.mockito.configuration.MockitoConfiguration class
        GlobalConfiguration.validate();

        if (verificationMode != null) {
            Location location = verificationMode.getLocation();
            verificationMode = null;
            throw unfinishedVerificationException(location);
        }

        getArgumentMatcherStorage().validateState();
    }

    

when()方法会调用MockingProgresspullOngoingStubbing()方法获取OngoingStubbing。然后就可以通过OngoingStubbing设置stub的各种返回值。

    public OngoingStubbing<?> pullOngoingStubbing() {
        OngoingStubbing<?> temp = ongoingStubbing;
        ongoingStubbing = null;
        return temp;
    }

verify调用

	//===    MockitoCore
	public <T> T verify(T mock, VerificationMode mode) {
        if (mock == null) {
            throw nullPassedToVerify();
        }
        if (!isMock(mock)) {
            throw notAMockPassedToVerify(mock.getClass());
        }
        MockingProgress mockingProgress = mockingProgress();
        //获取验证模式。
        VerificationMode actualMode = mockingProgress.maybeVerifyLazily(mode);
        mockingProgress.verificationStarted(new MockAwareVerificationMode(mock, actualMode, mockingProgress.verificationListeners()));
        return mock;
    }

	//=== MockingProgressImpl
    public VerificationMode maybeVerifyLazily(VerificationMode mode) {
        return this.verificationStrategy.maybeVerifyLazily(mode);
    }

	//=== MockingProgressImpl
	//创建Listener容器。
    public Set<VerificationListener> verificationListeners() {
        final LinkedHashSet<VerificationListener> verificationListeners = new LinkedHashSet<VerificationListener>();

        for (MockitoListener listener : listeners) {
            if (listener instanceof VerificationListener) {
                verificationListeners.add((VerificationListener) listener);
            }
        }

        return verificationListeners;
    }
	//=== MockingProgressImpl
	//设置VerificationMode。
    public void verificationStarted(VerificationMode verify) {
        validateState();
        resetOngoingStubbing();
        verificationMode = new Localized(verify);
    }

handle涉及

    //=== MockingProgressImpl
    public void reportOngoingStubbing(OngoingStubbing iOngoingStubbing) {
        this.ongoingStubbing = iOngoingStubbing;
    }

匹配器

Mockito 2.1.0之后,匹配器与Hamcrest解耦,定义了ArgumentMatcher接口。在ArgumentMatchers定义了很多静态方法,构造ArgumentMatcher实例。包路径:ArgumentMatcherorg.mockito.internal.matchers

public interface ArgumentMatcher<T> {
    boolean matches(T argument);
}

静态方法

any, any, anyBoolean, anyByte, anyChar, anyCollection, anyCollectionOf, anyDouble, anyFloat, anyInt, anyIterable, anyIterableOf, anyList, anyListOf, anyLong, anyMap, anyMapOf, anyObject, anySet, anySetOf, anyShort, anyString, anyVararg, argThat, booleanThat, byteThat, charThat, contains, doubleThat, endsWith, eq, eq, eq, eq, eq, eq, eq, eq, eq, floatThat, intThat, isA, isNotNull, isNotNull, isNull, isNull, longThat, matches, matches, notNull, notNull, nullable, refEq, same, shortThat, startsWith

ArgumentCaptor

ArgumentCaptor是一个能够捕获参数值的特殊参数匹配器。在某些场景中,不光要对方法的返回值和调用进行验证,同时需要验证一系列交互后所传入方法的参数。那么我们可以用参数捕获器来捕获传入方法的参数进行验证,看它是否符合我们的要求。

通过ArgumentCaptor对象的forClass(Class<T> clazz)方法来构建ArgumentCaptor对象。然后便可在验证时对方法的参数进行捕获,最后验证捕获的参数值。如果方法有多个参数都要捕获验证,那就需要创建多个ArgumentCaptor对象处理。

    //用于保存捕获的参数
    private final CapturingMatcher<T> capturingMatcher = new CapturingMatcher<T>();
    private ArgumentCaptor(Class<? extends T> clazz) {
        this.clazz = clazz;
    }   
    public static <U,S extends U> ArgumentCaptor<U> forClass(Class<S> clazz) {
        return new ArgumentCaptor<U>(clazz);
    }

ArgumentCaptor的Api


argument.capture()  //捕获方法参数
argument.getValue() //获取方法参数值,如果方法进行了多次调用,它将返回最后一个参数值
argument.getAllValues() //方法进行多次调用后,返回多个参数值

CapturingMatcher

public class CapturingMatcher<T> implements ArgumentMatcher<T>, CapturesArguments, VarargMatcher, Serializable {
//保存捕获的参数
    private final LinkedList<Object> arguments = new LinkedList<Object>();
    
}    

参考

官网:https://site.mockito.org/ , https://github.com/mockito/mockito,

匹配器(Matcher):https://javadoc.io/static/org.mockito/mockito-core/3.9.0/org/mockito/Matchers.html

bytebuddy

Byte Buddy是致力于解决字节码操作instrumentation API 的复杂性的开源框架。Byte Buddy 所声称的目标是将显式的字节码操作隐藏在一个类型安全的领域特定语言背后。通过使用 Byte Buddy,任何熟悉 Java 编程语言的人都有望非常容易地进行字节码操作。

Byte Buddy是一个较高层级的抽象的字节码操作工具,相较于ASM而言。其实吧,Byte Buddy 本身也是基于 ASM API 实现的。

Mockito生成的Class

可以使用JVM的HSDB工具来查看mock生成的Class。Mockito生成的class的名称格式为:

codegen.java.util.List$MockitoMock$2104292027 @0x00000007c0235128

以codegen开头,后跟interface,然后是MockitoMock。

Class说明

package codegen.java.util;  //package根据mock的接口确定。
//以下是引入mockito生成的辅助类。
import codegen.java.util.List.MockitoMock.2104292027.auxiliary.7DJ06WP7;
import codegen.java.util.List.MockitoMock.2104292027.auxiliary.KpK3ZEDf;
import codegen.java.util.List.MockitoMock.2104292027.auxiliary.NJCNn1rp;
import codegen.java.util.List.MockitoMock.2104292027.auxiliary.PkMnkkjK;
import codegen.java.util.List.MockitoMock.2104292027.auxiliary.WPMlpJ7S;
import codegen.java.util.List.MockitoMock.2104292027.auxiliary.dAVk5zvB;
import codegen.java.util.List.MockitoMock.2104292027.auxiliary.pP7UZY0a;
import codegen.java.util.List.MockitoMock.2104292027.auxiliary.wMxmFLt1;
import codegen.java.util.List.MockitoMock.2104292027.auxiliary.yOBrfhSk;
//继承了List,MockAccess
public class List$MockitoMock$2104292027 implements List, MockAccess {
    private static final long serialVersionUID = 42L;
    //MockAccess
    private MockMethodInterceptor mockitoInterceptor;

    public List$MockitoMock$2104292027() {
    }

    //List接口的方法。
    static {
        cachedValue$FPJFWYZr$gs4cee0 = List.class.getMethod("remove", Integer.TYPE);
        cachedValue$FPJFWYZr$77a53p0 = List.class.getMethod("lastIndexOf", Object.class);
        cachedValue$FPJFWYZr$479u1c1 = List.class.getMethod("size");
        cachedValue$FPJFWYZr$pa58dn1 = List.class.getMethod("toArray");
        cachedValue$FPJFWYZr$2v2l442 = List.class.getMethod("retainAll", Collection.class);
        cachedValue$FPJFWYZr$itsld03 = List.class.getMethod("iterator");
        cachedValue$FPJFWYZr$tm4die2 = List.class.getMethod("indexOf", Object.class);
        cachedValue$FPJFWYZr$idijvh3 = List.class.getMethod("subList", Integer.TYPE, Integer.TYPE);
        cachedValue$FPJFWYZr$ialm821 = List.class.getMethod("spliterator");
        cachedValue$FPJFWYZr$vv27a83 = List.class.getMethod("listIterator", Integer.TYPE);
        cachedValue$FPJFWYZr$4cscpe1 = Object.class.getMethod("toString");
        cachedValue$FPJFWYZr$pqjhh82 = List.class.getMethod("addAll", Integer.TYPE, Collection.class);
        cachedValue$FPJFWYZr$bp48n33 = List.class.getMethod("clear");
        cachedValue$FPJFWYZr$8o98bj1 = List.class.getMethod("containsAll", Collection.class);
        cachedValue$FPJFWYZr$3um2h43 = List.class.getMethod("removeAll", Collection.class);
        cachedValue$FPJFWYZr$ascqpd0 = Iterable.class.getMethod("forEach", Consumer.class);
        cachedValue$FPJFWYZr$5p89p02 = List.class.getMethod("set", Integer.TYPE, Object.class);
        cachedValue$FPJFWYZr$g7qoll1 = List.class.getMethod("sort", Comparator.class);
        cachedValue$FPJFWYZr$6epee82 = List.class.getMethod("addAll", Collection.class);
        cachedValue$FPJFWYZr$ivs3a83 = List.class.getMethod("listIterator");
        cachedValue$FPJFWYZr$bbf8080 = Collection.class.getMethod("parallelStream");
        cachedValue$FPJFWYZr$3us6oc3 = List.class.getMethod("add", Integer.TYPE, Object.class);
        cachedValue$FPJFWYZr$61en0h1 = List.class.getMethod("replaceAll", UnaryOperator.class);
        cachedValue$FPJFWYZr$7m9oaq0 = Object.class.getDeclaredMethod("clone");
        cachedValue$FPJFWYZr$4i8d8f1 = Collection.class.getMethod("stream");
        cachedValue$FPJFWYZr$v9lk1j0 = List.class.getMethod("remove", Object.class);
        cachedValue$FPJFWYZr$q0m7l61 = List.class.getMethod("contains", Object.class);
        cachedValue$FPJFWYZr$eqbjn92 = List.class.getMethod("toArray", Object[].class);
        cachedValue$FPJFWYZr$2ff4l01 = List.class.getMethod("get", Integer.TYPE);
        cachedValue$FPJFWYZr$aqin4c0 = Collection.class.getMethod("removeIf", Predicate.class);
        cachedValue$FPJFWYZr$sgg2351 = List.class.getMethod("add", Object.class);
        cachedValue$FPJFWYZr$dc8ju02 = List.class.getMethod("isEmpty");
    }

    //所有的方法实际都调用了DispatcherDefaultingToRealMethod.interceptAbstract。传入mockitoInterceptor
    //方法的Method对象。以及参数。
    public void add(int var1, Object var2) {
        DispatcherDefaultingToRealMethod.interceptAbstract(this, this.mockitoInterceptor, (Object)null, cachedValue$FPJFWYZr$3us6oc3, new Object[]{var1, var2});
    }
    //父类方法
    public void replaceAll(UnaryOperator var1) {
        DispatcherDefaultingToRealMethod.interceptSuperCallable(this, this.mockitoInterceptor, cachedValue$FPJFWYZr$61en0h1, new Object[]{var1}, new WPMlpJ7S(this, var1));
    }
    ... ...
   //MockAccess接口相关
   public void setMockitoInterceptor(MockMethodInterceptor var1) {
        this.mockitoInterceptor = var1;
    }

    public MockMethodInterceptor getMockitoInterceptor() {
        return this.mockitoInterceptor;
    } 
        
    

MockMethodInterceptor

interceptAbstract方法调用了MockMethodInterceptordoIntercept方法。

        //DispatcherDefaultingToRealMethod
        public static Object interceptAbstract(@This Object mock,
                                               @FieldValue("mockitoInterceptor") MockMethodInterceptor interceptor,
                                               @StubValue Object stubValue,
                                               @Origin Method invokedMethod,
                                               @AllArguments Object[] arguments) throws Throwable {
            if (interceptor == null) {
                return stubValue;
            }
            return interceptor.doIntercept(
                    mock,
                    invokedMethod,
                    arguments,
                    InterceptedInvocation.SuperMethod.IsIllegal.INSTANCE
            );
        }
       //DispatcherDefaultingToRealMethod
       public static Object interceptSuperCallable(@This Object mock,
                                                    @FieldValue("mockitoInterceptor") MockMethodInterceptor interceptor,
                                                    @Origin Method invokedMethod,
                                                    @AllArguments Object[] arguments,
                                                    @SuperCall(serializableProxy = true) Callable<?> superCall) throws Throwable {
            if (interceptor == null) {
                return superCall.call();
            }
            return interceptor.doIntercept(
                    mock,
                    invokedMethod,
                    arguments,
                    new InterceptedInvocation.SuperMethod.FromCallable(superCall)
            );
        }
    //MockMethodInterceptor
    Object doIntercept(Object mock,
                       Method invokedMethod,
                       Object[] arguments,
                       InterceptedInvocation.SuperMethod superMethod) throws Throwable {
        return doIntercept(
                mock,
                invokedMethod,
                arguments,
                superMethod,
                new LocationImpl()
        );
    }
    
    Object doIntercept(Object mock,
                       Method invokedMethod,
                       Object[] arguments,
                       InterceptedInvocation.SuperMethod superMethod,
                       Location location) throws Throwable {
        //调用InternalMockHandler的handle方法
        return handler.handle(
            //构造InterceptedInvocation
            new InterceptedInvocation(
            mock,
            createMockitoMethod(invokedMethod),
            arguments,
            superMethod,
            location,
            SequenceNumber.next()
        ));
    }

最后

以上就是老迟到冬日为你收集整理的Mockito详细介绍简介使用原理参考的全部内容,希望文章能够帮你解决Mockito详细介绍简介使用原理参考所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(57)

评论列表共有 0 条评论

立即
投稿
返回
顶部