mockito和PowerMock单元测试

mock和Mockito是什么

在软件开发中提及”mock”,通常理解为模拟对象。
为什么需要模拟? 在我们一开始学编程时,我们所写的对象通常都是独立的,并不依赖其他的类,也不会操作别的类。但实际上,软件中是充满依赖关系的,比如我们会基于service类写操作类,而service类又是基于数据访问类(DAO)的,依次下去,形成复杂的依赖关系。
单元测试的思路就是我们想在不涉及依赖关系的情况下测试代码。这种测试可以让你无视代码的依赖关系去测试代码的有效性。核心思想就是如果代码按设计正常工作,并且依赖关系也正常,那么他们应该会同时工作正常。
有些时候,我们代码所需要的依赖可能尚未开发完成,甚至还不存在,那如何让我们的开发进行下去呢?使用mock可以让开发进行下去,mock技术的目的和作用就是模拟一些在应用中不容易构造或者比较复杂的对象,从而把测试与测试边界以外的对象隔离开
我们可以自己编写自定义的Mock对象实现mock技术,但是编写自定义的Mock对象需要额外的编码工作,同时也可能引入错误。现在实现mock技术的优秀开源框架有很多,Mockito就是一个优秀的用于单元测试的mock框架

PowerMock概述

现如今比较流行的Mock工具如jMock,EasyMock,Mockito等都有一个共同的缺点:不能mock静态、final、私有方法等。而PowerMock能够完美的弥补以上三个Mock工具的不足。
PowerMock是一个扩展了其它如EasyMock等mock框架的、功能更加强大的框架。PowerMock使用一个自定义类加载器和字节码操作来模拟静态方法、构造函数、final类和方法、私有方法、去除静态初始化器等。目前PowerMock支持JUnit和TestNG。缺点是缺少文档。
PowerMock主要用于打桩。比如:方法A的参数需要传入实例B,方法A需要调用B的某个方法B.C()。方法C因为耗时长或者根本没有实现或者其他不方便在单元测试中实现等原因,需要伪造返回,此时PowerMock即可派上用场。

PowerMock常用注解

  • @RunWith(PowerMockRunner.class)和@PrepareForTest( { YourClass.class })
    如果你的测试用例里没有使用注解@PrepareForTest,那么可以不用加注解@RunWith(PowerMockRunner.class),反之亦然。当你需要使用PowerMock强大功能(Mock静态、final、私有方法等)的时候,就需要加注解@PrepareForTest。
  • @mock
    @Mock针对接口生成Mock类,我们是没法调用到真实的实现类的方法。是用来内部打桩测试使用的。
  • @spy
    需要赋予一个instance,需要new一个对象。可以为真实对象创建一个监控(spy)对象。应该尽量少的使用spy对象,使用时也需要小心。如果没有给这个函数打桩,那么就会调用真实的数据。例如:
List list = new LinkedList();
List spy = spy(list);
//因为调用spy.get(0)时会调用真实对象的get(0)函数,此时会发生IndexOutOfBoundsException异常
System.out.println(spy.get(0));

可以使用doReturn或者thenReturn来进行打桩:

when(spy.get(0)).thenReturn("foo");
doReturn("foo").when(spy).get(0);
  • @InjectMocks
    如果被测试类标记了此注解,mockito会自动注入mock或spy成员。例如我们测试service类时,就可以分别对dao和service类这么声明:
@Mock
private Dao dao; // mock 一个DAO层的接口
@InjectMocks
private ServiceImpl service;

注意:
必须使用@RunWith(MockitoJUnitRunner.class) 或 Mockito.initMocks(this)进行mocks的初始化和注入。

PowerMock常用场景

  • 模拟公共方法
//对无返回值的方法,后内部执行逻辑会被空调用覆盖
Mockito.doNothing().when(userService).doMethod(any(String.class)); 
//有返回值的方法 
when(userService.doMethod(any(String.class))).thenReturn("mock sayHello!");
  • 模拟私有方法
// 模拟返回值私有方法.
PowerMockito.doReturn("mock").when(userService, "privateMethod", any(String.class)); 
// 模拟私有空方法. 
PowerMockito.doNothing().when(userService, " privateMethod ", any(String.class));

MAVEN依赖

<dependency>
   <groupId>junit</groupId>
   <artifactId>junit</artifactId>
   <version>4.9</version>
   <scope>test</scope>
</dependency>
<dependency>
   <groupId>org.powermock</groupId>
   <artifactId>powermock-module-junit4</artifactId>
   <version>1.6.5</version>
   <scope>test</scope>
</dependency>
<dependency>
   <groupId>org.powermock</groupId>
   <artifactId>powermock-api-mockito</artifactId>
   <version>1.6.5</version>
   <scope>test</scope>
</dependency>

代码测试

  • 业务代码:
    UserAction:
public void executeForPublic(String something)
{ 
userService.sayHi(something); 
System.out.println(userService.sayHello(something)); 
}

UserService:

public void sayHi(String arg)
{ 
System.out.println("real"+arg+"!"); 
} 
public String sayHello(String arg)
{ 
return "real"+arg+"!"; 
}
  • 测试代码:
@RunWith(PowerMockRunner.class) 
@PrepareForTest({UserService.class,UserAction.class}) 
public class MockForPrivateDemo {
    @Mock
    private UserService userService;
    @InjectMocks
    private UserAction userAction;

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
    }

    @Test 
    public void demo() throws Exception {
        //有返回值的方法 
        when(userService.sayHello(any(String.class))).thenReturn("mock sayHello!");
        userAction. executeForPublic("hello");
    }
}

输出:mock sayHello!

参考链接

单元测试系列:Mock工具之Mockito实战
【mockito】单元测试之mockito简单使用
PowerMockito使用详解
Mock
Mockito使用指南
手把手教你 Mockito 的使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值