在SpringTest中将Mockito的mock对象通过spring注入使用
转载:https://blog.csdn.net/m0_38043362/article/details/80111957
1. 原理介绍
通过BeanFactoryPostProcessor向BeanFactory中注册需要进行Mock的对象,使当前Bean容器在依赖注入时使用
我们提供的Mock对象注入到实例中使用。
具体需要交给容器管理的mock实例,是通过TestExecutionListener在容器开始启动前去解析当前测试类中的使用@Mock
注解的字段,然后根据类型创建对应的Mock实例,将创建出来的Mock实例通过BeanFactoryPostProcessor注册到容器中,
以供依赖注入使用。
2.代码实现
注册Mock实例部分
public class MockitoBeansPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
Map<Class<?>, MockitoBeansTestExecutionListener.MockBeanWrapper> allMockBeans = MockitoBeansTestExecutionListener.resolvedAllMockBeans();
for (Map.Entry<Class<?>, MockitoBeansTestExecutionListener.MockBeanWrapper> mockBeanWrapperEntry : allMockBeans.entrySet()) {
beanFactory.registerResolvableDependency(mockBeanWrapperEntry.getKey(), mockBeanWrapperEntry.getValue().getMockObject());
}
}
}
解析@Mock注解部分
public class MockitoBeansTestExecutionListener extends AbstractTestExecutionListener {
private static final Map<Class<?>, MockBeanWrapper> mockBeans = new ConcurrentHashMap<>(30);
private static final Map<Class<?>, List<Field>> injectMockBeans = new ConcurrentHashMap<>(30);
private static boolean hasInitialized = false;
public static Map<Class<?>, MockBeanWrapper> resolvedAllMockBeans() {
Assert.isTrue(hasInitialized);
return Collections.unmodifiableMap(mockBeans);
}
@Override
public void beforeTestClass(TestContext testContext) throws Exception {
Field[] declaredFields = testContext.getTestClass().getDeclaredFields();
//将需要mock的对象创建出来
for (Field field : declaredFields) {
Mock mockAnnon = field.getAnnotation(Mock.class);
if (mockAnnon != null) {
MockBeanWrapper wrapper = new MockBeanWrapper();
Class<?> type = field.getType();
wrapper.setMockObject(Mockito.mock(type));
wrapper.setBeanType(type);
wrapper.setBeanName(field.getName());
mockBeans.putIfAbsent(wrapper.getBeanType(), wrapper);
injectMockBeans.compute(testContext.getTestClass(), (targetClass, waitInjectFields) -> {
if (waitInjectFields == null) {
waitInjectFields = new ArrayList<>();
}
waitInjectFields.add(field);
return waitInjectFields;
});
}
}
hasInitialized = true;
}
@Override
public void beforeTestMethod(TestContext testContext) throws Exception {
Object testInstance = testContext.getTestInstance();
List<Field> fields = injectMockBeans.get(testContext.getTestClass());
if (fields != null) {
for (Field field : fields) {
field.setAccessible(true);
field.set(testInstance, mockBeans.get(field.getType()).getMockObject());
}
}
}
public class MockBeanWrapper {
private String beanName;
private Class<?> beanType;
private Object mockObject;
public String getBeanName() {
return beanName;
}
public void setBeanName(String beanName) {
this.beanName = beanName;
}
public Class<?> getBeanType() {
return beanType;
}
public void setBeanType(Class<?> beanType) {
this.beanType = beanType;
}
public Object getMockObject() {
return mockObject;
}
public void setMockObject(Object mockObject) {
this.mockObject = mockObject;
}
}
}
3.使用Demo
MessageSupplier是将要进行Mock的接口
public interface MessageSupplier {
String getMessage();
}
这个是依赖MessageSupplier的实例类
@Service
public class SomeService {
@Autowired
MessageSupplier messageSupplier;
public void printMessage() {
System.out.println(messageSupplier.getMessage());
}
}
单元测试类
@TestExecutionListeners({MockitoBeansTestExecutionListener.class})
@ContextConfiguration(classes = {SimpleTestCase.class})
@ComponentScan(basePackageClasses = {SimpleTestCase.class})
public class SimpleTestCase extends AbstractJUnit4SpringContextTests {
@Autowired
private SomeService someService;
@Mock
MessageSupplier messageSupplier;
@Test
public void test() {
doReturn("this is mock message.")
.when(messageSupplier)
.getMessage();
someService.printMessage(); //输出this is mock message.
}
@Bean
public BeanFactoryPostProcessor mockBeansPostProcessor(){
return new MockitoBeansPostProcessor();
}
}
4.总结
在使用微服务的系统架构中,做一次单元测试会比较麻烦,可能需要启N多关联服务或者去连接N多关联服务。
这就使得单元测试很难实行,在这种情况下可以通过上面的方法将在本模块中不存在的实例都通过Mock实例
使用,这样使用Mockito中的doReturn等方法来模拟输入,去测试相关的代码片段。
在SpringTest中将Mockito的mock对象通过spring注入使用的更多相关文章
- 基于spring与mockito单元测试Mock对象注入
转载:http://www.blogjava.net/qileilove/archive/2014/03/07/410713.html 1.关键词 单元测试.spring.mockito 2.概述 单 ...
- Mockito中@Mock与@InjectMock
Mockito是java单元测试中,最常用的mck工具之一,提供了诸多打桩方法和注解.其中有两个比较常用的注解,@Mock和@InjectMock,名字和在代码中使用 的位置都很像,对于初学者,很容易 ...
- Mockito 如何 mock 返回值为 void 的方法
转载:https://unmi.cc/mockito-how-to-mock-void-method/#more-7748 最初接触 Mockito 还思考并尝试过如何用它来 mock 返回值为 vo ...
- dubbo应用程序的单元测试环境搭建(springtest,powermock,mockito)
转:http://blog.csdn.net/yys79/article/details/66472797 最近,项目中频繁用到dubbo,而且java工程用引用了几十个关联系统的服务(如用户认证,基 ...
- Mockito如何mock一条链式调用
在写单元测试的时候,不免可能需要mock一些对象出来,并且mock一些方法调用去返回一个自己想要的对象.一般的使用是这样的: FinalPumpkin pumpkin = mock(FinalPump ...
- java中将list、map对象写入文件
链接地址:http://blog.sina.com.cn/s/blog_4a4f9fb50101p6jv.html 推荐:凤爪女瓜子男怪象该谁反思伦敦房价为什么持续暴涨 × wvqusrtg个 ...
- 简单介绍如何使用PowerMock和Mockito来mock 1. 构造函数 2. 静态函数 3. 枚举实现的单例 4. 选择参数值做为函数的返回值(转)
本文将简单介绍如何使用PowerMock和Mockito来mock1. 构造函数2. 静态函数3. 枚举实现的单例4. 选择参数值做为函数的返回值5. 在调用mock出来的方法中,改变方法参数的值 一 ...
- 持续集成之路 —— Mock对象引起的测试失败
今天遇到了一个很奇怪的问题,纠结了好久.在和同事念叨这个问题时,突然想到了问题所在. 问题现象: 在一个Service的单元测试类中有八个测试用例,单独运行时都可以正常通过.可是一旦一起运行时,总是会 ...
- Mockito不能mock final类的解决办法
Mockito是很常用的测试工具,使用过程中可能会遇到下面的问题: Mockito cannot mock/spy because : - final class 问题重现: 引入该依赖到项目的mav ...
随机推荐
- 78-WS2812-Library (STM32F4)
78-WS2812-Library (STM32F4) //-------------------------------------------------------------- // File ...
- bitnami redmine配置全过程
常见问题: 我在自己的机器上面配置完毕以后,移植到另外一台机器上面,登陆页面总是在检查network,并且最后网络加载失败,不论我是用桥接还是NAT方式连接.登陆系统以后,我尝试连接网络失败,尝试执行 ...
- delphi project of object
http://www.cnblogs.com/ywangzi/archive/2012/08/28/2659811.html 其实要了解这些东西,适当的学些反汇编,WINDOWS内存管理机制,PE结构 ...
- ASP.NET Web API中通过ETag实现缓存
通常情况下Server是无状态的,在ASP.NET Web API中,我们可以让服务端响应体中产生ETag属性,起到缓存的作用.大致实现原理是: 1.服务端的响应体中返回一个ETag属性2.客户端通过 ...
- WordPress主题开发:WP_Query常用参数
常用参数 用途 调用文章或页面 s 查询和某个关键词相关的所有的文章/页面信息 p 文章或页面id post__in 多篇id post__not_in 多篇id以外 post_type 查询的信息类 ...
- ArrayList 排序方法的性能对比
20000=>ZXP 二分法 getSeriesMinSort2(list) Time is 67000 20000=>循环 getSeriesMinSortFor(list) Time ...
- 侏罗纪世界2百度云在线观看迅雷下载高清BT下载
原名:Jurassic World: Fallen Kingdom 地区:美国 语言:英语 首播:2018-06-15(中国大陆) / 2018-06-22(美国) 电视台: 类型:动作 / 科幻 / ...
- 危机边缘第一季/全集Fringe迅雷下载
本季Fringe Season 2 第二季(2008)看点:一架从汉堡飞往波士顿航班安全着陆,飞机上的机组成员和乘客却全部死亡.这起离奇案件揭开了一连串奇异.危险事件的序幕. 故事将主要讲述年轻的FB ...
- Android性能检测工具——traceview
之前的几篇文章中介绍了android中常用的一些工具,今天介绍的工具也是比较实用和方便的,它可以用量化的指标告诉我们哪个方法执行的时间最长,被调用的次数最多,有没有重复调用.下面我们就来看看它是怎么为 ...
- Android Studio导入项目的中文注释乱码解决方法
在Android studio中,导入Android的项目后,容易出现项目文件的中文乱码,中文无法正常显示,变成了一些格子问号之类的,导致无法查看中文的注释,下面来看看导入项目和解决乱码 ...