Mockito各场景使用介绍
场景1:某三方接口所有方法都需要Mock
实现方式1-配置configrution bean
实现方式2-在application context中配置mock bean
场景2:某三方接口部分方法mock
实现方式1-spy方式:
实现方式2-callRealMethod():
场景3:影响范围只在单个测试类
实现方式1-使用ReflectionTestUtils解决依赖注入Mock对象
实现方式2-官方介绍的@mock,@injectMock方式
场景4.mock代理类
实现方式1-通过AddtionalAnswer.delegateto(instance)
场景1:某三方接口所有方法都需要Mock
实现方式1-配置configrution bean
step1:创建一个类如下:
@Configuration
public class WithdrawConfiguration {
@Bean
@Primary
public SauronBankService sauronBankService() {
SauronBankService mock = mock(SauronBankService.class);
BankCardDTO t = new BankCardDTO();
t.setBankId((short) 11);
t.setCardholder("hehe");
t.setCardId("32423423423");
t.setBankName("中国银行 ");
t.setAcc_type((byte) 1);
t.setBranch_bank_name("武汉分行");
t.setProvince("湖北省");
t.setCity("武汉市");
when(mock.queryBankCard(anyInt(), anyLong(), Mockito.<String> any()))
.thenReturn(t);
return mock;
}
@Bean
@Primary
public MasspayClient masspayClient() {
// then return this.
MasspayClient client = Mockito.mock(MasspayClient.class);
MasspayResult<WithdrawResponse> withdrawResponseMasspayResult = new MasspayResult<>(
ResultCode.SUCCESS);
when(client.callLadon(any(WithdrawRequest.class)))
.thenReturn(withdrawResponseMasspayResult);
MasspayResult<CancelResponse> cancelResponseMasspayResult = new MasspayResult<>(
ResultCode.SUCCESS);
when(client.cancelCallLadon(any(CancelRequest.class)))
.thenReturn(cancelResponseMasspayResult);
return client;
}
}
step2.在application context中加载如下:
实现方式2-在application context中配置mock bean
step1:pom文件中加载mockito dependency
step2:在application context中声明mock bean,参考如下:
<bean id="mockOrderManageFacade" class="org.mockito.Mockito"
factory-method="mock">
<constructor-arg value="me.ele.transcore.comm.facade.api.OrderManageFacade">
</constructor-arg>
</bean>
注意事项:
<!-- id必须和biz中autowired的属性值一致,然后在测试类中@Resource该对象,stub该对象的方法指定返回数据 -->
<!-- 对其他测试类的影响:有关联测试类调用该接口时,接口中的其他方法默认返回null;解决影响:在其他相关联的测试指定返回值 -->
step3:在测试类中添加mock代码,参考如下:
MockitoAnnotations.initMocks(this);//初始化mock bean
WithdrawCancelCallBackResponse mockResponse = new WithdrawCancelCallBackResponse();
mockResponse.setResultCode(
ResultCodeEnum.FAIL_WITHDRAW_CALLBACK_AMOUNT_NO_CONSISTENT
.getKey());//
Mockito.when(mockOrderManageFacade.withdrawCancelCallBack(
Mockito.any(WithdrawCancelCallBackRequest.class)))
.thenReturn(mockResponse);//mock为期望的response
场景2:某三方接口部分方法mock
- 部分mock解释说明:部分mock是说一个类的方法有些是实际调用,有些是使用mockito的stubbing(桩实现)
- mockito实现部分mock的两种方式:spy和callRealMethod()
- Spy类就可以满足我们的要求。如果一个方法定制了返回值或者异常,那么就会按照定制的方式被调用执行;如果一个方法没被定制,那么调用的就是真实类的方法。
- 如果我们定制了一个方法A后,再下一个测试方法中又想调用真实方法,那么只需在方法A被调用前,调用Mockito.reset(spyObject)。
实现方式1-spy方式:
@Test
public void spy_Simple_demo(){
List<String> list = new LinkedList<String>();
List<String> spy = spy(list);
when(spy.size()).thenReturn(100);
spy.add("one");
spy.add("two");
/* spy的原理是,如果不打桩默认都会执行真实的方法,如果打桩则返回桩实现。
可以看出spy.size()通过桩实现返回了值100,而spy.get(0)则返回了实际值*/
assertEquals(spy.get(0), "one");
assertEquals(100, spy.size());
}
注意事项:当调用方法如when().thenReturn()时,实际上还是调用了实际方法。
参考如下:
@Test
public void spy_Procession_Demo() {
Jack spyJack = spy(new Jack());
//使用spy的桩实现实际还是会调用stub的方法,只是返回了stub的值
when(spyJack.go()).thenReturn(false);
assertFalse(spyJack.go());
//不会调用stub的方法
doReturn(false).when(spyJack).go();
assertFalse(spyJack.go());
}
实现方式2-callRealMethod():
package callRealMethod;
import org.junit.Test;
import static org.mockito.Mockito.*;
public class CallMethodDemo {
@Test
public void callRealMethodTest() {
Jerry jerry = mock(Jerry.class);
doCallRealMethod().when(jerry).doSomeThingA();
doCallRealMethod().when(jerry).doSomeThingB();
jerry.goHome();
verify(jerry).doSomeThingA();
verify(jerry).doSomeThingB();
}
}
class Jerry {
public void goHome() {
doSomeThingA();
doSomeThingB();
}
// real invoke it.
public void doSomeThingB() {
System.out.println("good day");
}
// auto mock method by mockito
public void doSomeThingA() {
System.out.println("you should not see this message.");
}
}
场景3:影响范围只在单个测试类
优点:mock对象影响范围只在单个测试类,不影响其他测试类。
实现方式1-使用ReflectionTestUtils解决依赖注入Mock对象
@Component
public class WithdrawApplicationTest extends AccountWithdrawFacadeBaseTest {
@Captor
private ArgumentCaptor<WithdrawApplicationRequest> captor;
@Mock
private CheckPasswordComponent mockCheckPasswordComponent;
@Autowired
private CheckPasswordComponent checkPasswordComponent;
@Autowired
private AccountWithdrawWithoutLadonBiz acccountWithdrawWithoutLadonBiz;
@Autowired
private AccountWithdrawFacade withdrawFacade;
@Test
public void withdrawTest() {
WithdrawApplicationRequest applyReq = new WithdrawApplicationRequest();
applyReq.setAccountType(TYPE);
applyReq.setCustomerId(ZEUS_CUSTOMER_ID);
applyReq.setRequestPartyId(ZEUS_SOURCE_PARTY_ID);
applyReq.setSourcePartyId(ZEUS_SOURCE_PARTY_ID);
applyReq.setTransactionChannel("h5");
applyReq.setPassword(ZEUS_PASSWORD);
applyReq.setPartyTransactionId(
new Timestamp(System.currentTimeMillis()).toString());
applyReq.setPartyTransactionTime(
new Timestamp(System.currentTimeMillis()));
applyReq.setTransAmount(new BigDecimal("1000"));
applyReq.setSign(GenerateSignUtils.generateSign(applyReq,
"fd219e782ecebf0bc8f4a83e43248b45"));
given(mockCheckPasswordComponent.restCountByPassword(Mockito.anyInt(),
Mockito.anyLong(), Mockito.anyByte())).willReturn(3);
WithdrawApplicationResponse response = withdrawFacade
.withdrawApplication(applyReq);
verify(mockCheckPasswordComponent, times(1)).restCountByPassword(
Mockito.anyInt(), Mockito.anyLong(), Mockito.anyByte());
Assert.assertEquals(response.getRestAttempts(), 3);
System.err.println(JsonUtil.toFormatJson(response));
Assert.assertEquals(response.getTransactionResultDescription(), "成功");
}
@BeforeClass
private void beforeClass() {
MockitoAnnotations.initMocks(this);
try {
ReflectionTestUtils.setField(
AopTargetUtils.getTarget(acccountWithdrawWithoutLadonBiz),
"checkPasswordComponent", mockCheckPasswordComponent);
} catch (Exception e) {
logger.error("", e);
}
}
@AfterClass
public void clearMocks() throws Exception {
ReflectionTestUtils.setField(
AopTargetUtils.getTarget(acccountWithdrawWithoutLadonBiz),
"checkPasswordComponent", checkPasswordComponent);// 还原为真实bean,不影响其他case
}
}
实现方式2-官方介绍的@mock,@injectMock方式
说明:据实验,这种模式碰到多层内嵌bean时不生效,所以暂不举例说明,参考如下文档。
官方文档参考:https://static.javadoc.io/org.mockito/mockito-core/2.10.0/org/mockito/Mockito.html
场景4.mock代理类
实现方式1-通过AddtionalAnswer.delegateto(instance)
转载:https://www.cnblogs.com/danqiu/p/7531538.html
Mockito各场景使用介绍的更多相关文章
- List集合的总结和应用场景的介绍
1.List的整体介绍 List 是一个接口,它继承于Collection的接口,它代表着有序的队列.list的实现类对象中每一个元素都有一个索引值,能够按照索引值进行元素查找. AbstractLi ...
- PHP的设计模式及场景应用介绍
有大量的文章解释什么是设计模式,如何实现设计模式,网络上不需要再写一篇这样的文章.相反,在本文中我们更多的讨论什么时候用和为什么要用,而不是用哪一个和如何使用. 我将会为这些设计模式描绘不同的场景和案 ...
- 消息中间件activemq的使用场景介绍(结合springboot的示例)
一.消息队列概述 消息队列中间件是分布式系统中重要的组件,主要解决应用耦合,异步消息,流量削锋等问题.实现高性能,高可用,可伸缩和最终一致性架构.是大型分布式系统不可缺少的中间件. 目前在生产环境,使 ...
- 从Client应用场景介绍IdentityServer4(一)
原文:从Client应用场景介绍IdentityServer4(一) 一.背景 IdentityServer4的介绍将不再叙述,百度下可以找到,且官网的快速入门例子也有翻译的版本.这里主要从Clien ...
- Android线程管理之ThreadLocal理解及应用场景
前言: 最近在学习总结Android的动画效果,当学到Android属性动画的时候大致看了下源代码,里面的AnimationHandler存取使用了ThreadLocal,激起了我很大的好奇心以及兴趣 ...
- RunLoop 总结:RunLoop的应用场景(一)
参考资料 好的书籍都是值得反复看的,那好的文章,好的资料也值得我们反复看.我们在不同的阶段来相同的文章或资料或书籍都能有不同的收获,那它就是好文章,好书籍,好资料.关于iOS 中的RunLoop资料非 ...
- Netsharp介绍
1.1 Netsharp是什么 Netsharp定义: Netsharp业务基础平台 = 1.系统框架 + 2.元数据 + 3.平台工具 + 4.基础业务 + 5.二次开发 此五个概念请参考什 ...
- cocos2d-x中的导演、场景、层和精灵
场景(Scenes) 场景在cocos2d-x中是CCScene类实现的,是应用程序流中独立的一部分.一个cocos2dx应用程序可以有许多场景,但是在某一时刻,只有一个场景在运行. 比如,你有一个游 ...
- Mockito--完整功能介绍(转)
public interface DBAccess { int delete(String moi,String moc) throws Exception; void create(String m ...
随机推荐
- 【stanford C++】容器III——Vector类
主要介绍如下5个容器类——Vector, Stack,Queue,Map和Set,各个都表示一重要的抽象数据类型.另外,各个类都是一些简单类型的值的集合,所以称它们为容器类. 暂且我们先不需要知道它们 ...
- JVM菜鸟进阶高手之路
http://www.jianshu.com/u/3def157aab07?utm_medium=note-author-link&utm_source=mobile
- 改变窗体大小视图区图形也会跟着变化 MFC
怎样实现窗体缩放,视图区里的图形也会跟着变化 在CMFCView类中加入三个消息函数: 在类向导中选中CMFCView类,点击右键---->类向导------>消息--------> ...
- SQLServer2008:在查看表记录或者修改存储过程时出现错误。错误消息为: 目录名无效
登陆数据库后,右键打开表提示:目录名无效,执行SQL语句也提示有错误,本来想重装的这个肯定能解决,但是这个方法真的不视为上上策啊,于是在网上找到了这个解决办法,还真是立即见效啊!分享给大家,希望有帮助 ...
- [SQLite][Error Code] 21 misuse
若使用SQLite API時,出現错误代码21(misuse),可能是你的SQLiteConnection同時打開(Open)了兩個相同的Data source,所造成的错误. 解決方法:检查代码 ...
- clojure中符号symbols 和变量vars的正确理解
原地址 http://stackoverflow.com/questions/11662084/why-does-clojure-distinguish-between-symbols-and-va ...
- .NET零基础入门09:SQL必知必会
一:前言 仿佛到了更进一步的时候了,每一个程序员迟早都会遇到数据存储的问题.我们拿什么来存储程序产生的数据?举例来说,用什么来存储我们的打老鼠游戏每次的成绩呢?选择如下: 1:内存中.缺点,退出游戏, ...
- MAC 上的 Live Writer : ecto
ecto 在这里: http://illuminex.com/ecto/ 它是一款 MAC 上的 live writer,对我来说,没有 writer 之类的工具,我就宁可不写博客。 测试插入图片 测 ...
- Java命令学习系列(六)——jinfo
jinfo可以输出java进程.core文件或远程debug服务器的配置信息.这些配置信息包括JAVA系统参数及命令行参数,如果进程运行在64位虚拟机上,需要指明-J-d64参数,如:jinfo -J ...
- [转]php curl经典最常用的5个例子
转自: http://www.jb100.net/html/content-22-821-1.html php curl常用的5个例子 我用php ,curl主要是抓取数据,当然我们可以用其他的方法来 ...