添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
霸气的胡萝卜  ·  Jest | Sysuke's World·  2 周前    · 
大鼻子的企鹅  ·  单元测试技巧·  2 天前    · 
聪明的足球  ·  Nginx udp代理-阿里云·  1 年前    · 

在后台接口开发之后,有必要进行单元测试,可以保证代码的交付质量,同时重构代码得时候,也可以更放心大胆;但是在测试的时候,对于一些不需要的服务,需要使用mock测试来mock函数或者方法;文章做个简单的记录,主要总结下mock,spy的区别,injectMocks的用法,以及PowerMock的使用来解决静态方法的mock;

1.mock和spy的区别

两者都可以注解到某个属性上,区别是用mock注解标注的变量,在调用时,除mock之外的其他方法不会进行调用的,只有声明的mock方法会直接返回给定的值;比如说mock标注在“serviceA”上,同时mock了serviceA中的fun1,如果在测试过程中调用了serviceA的fun2,那么是不会执行fun2的方法的;调用fun1会直接返回mock的返回结果;

spy注解的变量,根据声明的两种方式,当使用doReturn().when时,不进入方法体中调用;而使用when().thenReturn这种方式时,会进行到方法体执行,最后返回声明的结果;如果没有声明方法,那么spy会调用真实的函数的执行流程;下面通过个例子来说明下

定义个类,具体如下所示

public class Main {
    public String fun(String s) {
        System.out.println(s + " : fun");
        fun1(s);
        fun2(s);
        return null;
    public void fun1(String s) {
        System.out.println(s + " : fun1");
    private void fun2(String s) {
        System.out.println(s + " : fun2");
    public int getVal(){
        return 5;

先使用@Spy注解

import org.junit.Before;
import org.junit.Test;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doReturn;
public class MainTest {
    private Main mainClass;
    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
        doReturn("SSS").when(mainClass).fun(anyString());
    @Test
    public void test() {
        String aaa = mainClass.fun("aaa");
        System.out.println(aaa);

使用doReturn().when方法来mock fun函数的返回结果;然后执行 测试test方法,返回结果,打印出sss

这里说明这种方式没有执行fun函数的内部;

然后修改下mock的声明方式,其它代码不动,修改如下

public class MainTest {
    private Main mainClass;
    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
        when(mainClass.fun(anyString())).thenReturn("SSS");
    @Test
    public void test() {
        String aaa = mainClass.fun("aaa");
        System.out.println(aaa);

执行结果如下所示

 : fun
 : fun1
 : fun2

说明这种声明的方式,会进入到方法体内部执行,最后再返回结果;

下面再看看mock的测试

public class MainTest {
    @Mock
    private Main mainClass;
    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
        doReturn("SSS").when(mainClass).fun(anyString());
    @Test
    public void test() {
        String aaa = mainClass.fun("aaa");
        System.out.println(aaa);

返回结果SSS,说明mock的方法会直接返回;不会进入方法内部;

下面把mock的声明去掉,如下所示

public class MainTest {
    @Mock
    private Main mainClass;
    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
    @Test
    public void test() {
        String aaa = mainClass.fun("aaa");
        System.out.println(aaa);

这里会打印null,因为mock的类的方法不会调用的,只有声明的mock方法会直接返回结果;如果改成@Spy来注解,那么会调用真实的方法执行的;这也是mock和spy的区别;

2.InjectMocks

标注为mock或者spy的类可以注入到添加了InjectMocks的类中;举个例子,Service调用Repository中的方法进行数据库操作,我们要mock respository向数据库插入数据的操作,那么就可以

public Class MainTest{
    @InjectMocks
    private MyService service;
    @Mock
    private Repository repository;

这样service中调用的就是mock的repository中的方法了;但是有个问题,如果service中注入其他的服务,那么其他的服务都是null;需要通过ReflectionTestUtils.setField注入对应的属性才可以;而且InjectMocks和Autowired添加到同一个属性上,有时会存在InjectMock失败的情况,但是InjectMocks失败是没有通知的,这点需要注意下;

3.静态方法的mock

mockito缺点是无法对静态的方法进行mock测试,静态方法的测试需要引入powermock;

testCompile "org.mockito:mockito-core:2.8.9"
testCompile "org.powermock:powermock-api-mockito2:1.7.1"
testCompile "org.powermock:powermock-module-junit4:1.7.1"

对应的需要引入的jar如图所示,同时需要导入的注解需要进行下面的修改

@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(SpringRunner.class)
@PowerMockIgnore({"javax.management.*", "javax.net.ssl.*"})
@PrepareForTest(UserEntityRoleContext.class)
@SpringBootTest(classes = CrmApp.class)
PowerMockito.mockStatic(UserEntityRoleContext.class);
        PowerMockito.when(UserEntityRoleContext.getRoles(any())).thenReturn(new HashSet<>(Arrays.asList(new String[]{"aaa", "bbb"})));

mock的时候使用上面的方式来mock静态方法;

https://www.baeldung.com/mockito-annotations

https://blog.csdn.net/qq_30141957/article/details/81273829

https://blog.csdn.net/Aeroleo/article/details/49946999?locationNum=14&fps=1

https://www.jianshu.com/p/adee7d28cb59

  在软件开发的世界之外 "mock"一词是指模仿或者效仿. 因此可以将“mock”理解为一个替身,替代者. 在软件开发中提及"mock",通常理解为模拟对象或者Fake. 译者注:mock等多代表的是对被模拟对   @Test注解的public void方法将会被当做测试用例   JUnit每次都会创建一个新的测试实例,然后调用@Test注解方法,任何异常的抛出都会认为测试失败 @Test注解提供2个参数:   I.”expected”,定义测试方法应该抛出的异常,如果测试方法没有抛出异常或者抛出了一个同的异常,测试失败 @Test(expected = IllegalArgumentException.class) 表示验证这个测试方法将抛出 Ille