概述
文章目录
- 简介
- 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对象使用MockMaker
。MockMaker
是个接口,用于创建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对象的每个方法都生成了代码,最终调用MockHandlerImpl
的handle()
方法。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()方法会调用MockingProgress
的pullOngoingStubbing()
方法获取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
方法调用了MockMethodInterceptor
的doIntercept
方法。
//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详细介绍简介使用原理参考所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复