原理:
1、扫描包含 @Mock 注解的字段,创建对象并进行设置
2、扫描包含 @InjectMocks 注解的字段,并进行注入(执行注入的是mockito,不是spring)
3、配置mock数据
1、调用 @Mock 字段的方法,创建 stub --- 第一次调用
2、设置mock数据到 stub
4、执行调用
1、调用 @Mock 字段的方法,由于stub有数据,就返回mock的数据 --- 第二次调用
package cn.java.demo.user.service;
import cn.java.demo.user.dao.entity.User;
import cn.java.demo.user.dao.mapper.UserMapper;
import cn.java.demo.user.service.impl.UserServiceFacadeImpl;
import cn.java.demo.user.service.impl.UserServiceImpl;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.BDDMockito;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
/**
* 多级嵌套依赖
*/
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserServiceUseMockitoTest {
/**
* 注入mocker对象(执行注入的是mockito,不是spring)
*/
@InjectMocks
private UserServiceFacadeImpl userServiceFacadeImpl;
/**
* 创建mocker对象
*/
@Mock
private UserService userService;
/**
* 注入mocker对象(执行注入的是mockito,不是spring)
* <p>
* 创建一个实例,使用用@Mock(或@Spy)注解创建的mock将被注入到用该实例中
*/
@InjectMocks
private UserServiceImpl userServiceImpl;
/**
* 创建mocker对象
*/
@Mock
private UserMapper userMapper;
@Before
public void setUp() {
/*
1、获取注解引擎
1、创建 GLOBAL_CONFIGURATION,放入线程上下文
尝试加载 org.mockito.configuration.MockitoConfiguration 类,否则使用 org.mockito.configuration.DefaultMockitoConfiguration
2、获取注解引擎
org.mockito.internal.configuration.InjectingAnnotationEngine
2、使用注解引擎处理测试类
{
1、解析声明的mocker(解析标注@Mock注解的对象)
{
org.mockito.internal.configuration.InjectingAnnotationEngine.process(...)
{
1、委托处理 @Mocks, @Captors 等注解
org.mockito.internal.configuration.DefaultAnnotationEngine.process(...)
{
1、扫描测试类(UserServiceUseMockitoTest)的字段
for (Field field : fields)
{
1、获取处理结果;
1、获取《字段注解》的处理器,并执行处理器
如:@Mock 注解
{
org.mockito.internal.configuration.MockAnnotationProcessor.process(...)
{
1、创建handler
{
mockHandler = org.mockito.internal.handler.InvocationNotifierHandler
{
mockHandler : org.mockito.internal.handler.NullResultGuardian
{
delegate : org.mockito.internal.handler.MockHandlerImpl.MockHandlerImpl
{
mockSettings : org.mockito.internal.creation.settings.CreationSettings
{
typeToMock : cn.java.demo.user.dao.mapper.UserMapper,
xxx : org.mockito.internal.creation.MockSettingsImpl
{
defaultAnswer : org.mockito.internal.stubbing.defaultanswers.GloballyConfiguredAnswer
}
}
}
}
}
}
2、创建mocker
{
1、查找mocker创建器
{
PluginSwitch(插件切换器)
1、查找类路径下 "mockito-extensions/org.mockito.plugins.PluginSwitch" 文件
2、没查找到使用默认值:org.mockito.internal.configuration.plugins.DefaultPluginSwitch
mockMaker (mocker创建器)
1、查找类路径下 "mockito-extensions/org.mockito.plugins.MockMaker" 文件
2、没查找到使用默认值:org.mockito.internal.creation.cglib.CglibMockMaker
}
2、创建mocker
{
1、方法的拦截器
{
org.mockito.internal.creation.cglib.MethodInterceptorFilter
{
handler : org.mockito.internal.handler.InvocationNotifierHandler
mockSettings : org.mockito.internal.creation.settings.CreationSettings
}
}
2、创建代理对象
{
org.mockito.internal.creation.cglib.CglibMockMaker.createMock(settings, mockHandler);
{
使用 cglib.Enhancer 创建代理对象,并返回
{
1、在内存中生成《类的内容(byte)》
byte[] b = strategy.generate(this);
2、把《类的内容(byte)》 转成《class》
String className = ClassNameReader.getClassName(new ClassReader(b));
getClassNameCache(loader).add(className);
gen = ReflectUtils.defineClass(className, b, loader);
}
}
}
}
}
}
}
如:@Captor 注解
org.mockito.internal.configuration.CaptorAnnotationProcessor.process(...)
2、把处理《结果对象》作为值注入到《测试对象的字段(userMapper)》
{
// ...
}
}
}
2、自行处理 @Spies 注解
org.mockito.internal.configuration.SpyAnnotationEngine.process(...)
}
}
2、执行注入(解析标注 @InjectMocks 注解的对象)
{
org.mockito.internal.configuration.InjectingAnnotationEngine.processInjectMocks()
{
1、扫描含有 @InjectMocks 注解的字段列表 fields
2、扫描含有 @Spy、@Mock 注解的字段列表 mocks
3、执行注入,迭代fields对象列表,注入mocks含有的对象
{
for (Field field : fields) {
injectionStrategies.process(field, fieldOwner, mocks);
{
1、尝试《构造函数》注入
{
org.mockito.internal.configuration.injection.ConstructorInjection.process(...)
}
2、尝试《属性》注入
{
org.mockito.internal.configuration.injection.PropertyAndSetterInjection.process(...)
{
processInjection(...)
{
injectMockCandidates(...)
{
1、获取非 static & final 属性
orderedInstanceFieldsFrom(awaitingInjectionClazz)
2、注入
1、按《类型》匹配
org.mockito.internal.configuration.injection.filter.TypeBasedCandidateFilter.filterCandidate(...)
2、按《字段名》匹配
org.mockito.internal.configuration.injection.filter.NameBasedCandidateFilter
3、创建 setter
org.mockito.internal.configuration.injection.filter.FinalMockCandidateFilter
}
}
}
}
}
postInjectionStrategies.process(field, fieldOwner, mocks);
{
1、使用spy注入
{
org.mockito.internal.configuration.injection.SpyOnInjectedFieldsHandler.process(...)
}
}
}
} // end 执行注入
}
}
}
*/
MockitoAnnotations.initMocks(this); // 初始化Mock对象
}
@Test
public void getById() {
/*
《1、mocker数据》
1、调用代理对象 userMapper.getById(BDDMockito.anyLong())
1、调用 userMapper 代理对象,即执行:org.mockito.internal.handler.MockHandlerImpl.handle(...)
2、代理对象创建 OngoingStubbingImpl
mockingProgress.reportOngoingStubbing(ongoingStubbing);
2、when()
1、获取 OngoingStubbing 对象
mockingProgress.pullOngoingStubbing()
3、thenAnswer(...)
1、设置 OngoingStubbing 对象的属性
*/
if (false) { // 方式1
// 创建 stub
userMapper.getById(BDDMockito.anyLong()); // 进行了一次调用
// 配置 stub
BDDMockito.when(null).thenAnswer((InvocationOnMock invocationOnMock) -> { // 模拟userMapper
Long id = (Long) invocationOnMock.getArguments()[0];
if (null == id) {
return null;
} else if (Long.valueOf(1).equals(id)) {
return User.builder().
id(1L).
passWord("pwd1").
realName("realName1").
userName("userName1").
build();
} else {
return null;
}
});
} else { // 方式2
BDDMockito.when(userMapper.getById(BDDMockito.anyLong())).thenAnswer((InvocationOnMock invocationOnMock) -> { // 模拟userMapper
Long id = (Long) invocationOnMock.getArguments()[0];
if (null == id) {
return null;
} else if (Long.valueOf(1).equals(id)) {
return User.builder().
id(1L).
passWord("pwd1").
realName("realName1").
userName("userName1").
build();
} else {
return null;
}
});
}
/*
《2、执行 & 断言》
*/
Assert.assertEquals("pwd1", userServiceImpl.getById(1L).getPassWord());
System.out.println(userServiceImpl.getById(1L).getPassWord());
// 1、mocker数据
BDDMockito.when(userService.getById(BDDMockito.anyLong())).thenAnswer((InvocationOnMock invocationOnMock) -> { // 模拟userMapper
Long id = (Long) invocationOnMock.getArguments()[0];
return userServiceImpl.getById(id);
});
// 2、执行 & 断言
System.out.println(userServiceFacadeImpl.getById(1L));
}
}