栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

单元测试常用 -- Mock 框架

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

单元测试常用 -- Mock 框架

文章目录
  • **单元测试常用 -- Mock 框架**
    • **Mockito 框架**
      • **常用注解**
      • **示例代码**
    • **PowerMock 框架**
      • **Mock 入参对象**
      • **Mock 方法内部 new 出来的对象**
      • **Mock 普通对象的 final 方法**
      • **Mock 普通对象的静态方法、私有方法**
      • **踩坑指南**

单元测试常用 – Mock 框架 Mockito 框架 常用注解

@Mock:功能类似于 Spring 的注解 @Autowied,但不会真的注入单例,而是表示这个类要被 mock。

@InjectMocks:表示将该类里面被 Mock 注解的类进行注入。

@RunWith(MockitoJUnitRunner.class)

示例代码
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import org.powermock.api.mockito.PowerMockito;

// Runwith 用来提供测试环境,@Mock 以及 @InjectMocks 注解需要在一定的环境下才能生效
@RunWith(MockitoJUnitRunner.class)
public class TestMockito {

    // InjectMocks 注解。
    // 功能:不仅会 PerformService,同时 PerformService 里面如果含有 Mock 的类,Mockito 框架会帮我们进行自动注入
    @InjectMocks
    PerformService performService;

    // Mock 注解。
    // 功能:mock CalculatorService
    @Mock
    CalculatorService calculatorService;

    @Test
    public void testPerformService() {
        createMock();
        Assert.assertEquals(10, performService.perform(2,3));
    }

    private void createMock() {
        // 使用 Mockito 框架提供的 when 方法
        // 功能:当该方法被调用时,直接返回预定的值
        Mockito.when(calculatorService.add(Mockito.anyInt(), Mockito.anyInt())).thenReturn(5);
    }

}

正常情况下,我们使用 Mockito framework 就可以完成简单的 mock,但要实现更加高级的 mock 例如 mock 静态、final、私有方法等,Mockito framework 就不太够用了,这个时候就需要使用 PowerMockito。

PowerMock 框架

PowerMock 有两个重要的注解:

@RunWith(PowerMockRunner.class)

@PrepareForTest({xxx.class})

如果测试用例中没有使用注解@PrepareForTest,那么可以不添加@RunWith(PowerMockRunner.class)。

Mock 入参对象

使用方法:Mock 参数传递对象,这个没什么好说的,直接 PowerMockito.mock(xxx.class) 即可。

Student.java:

@Data
public class Student {
    private int age;
    private String name;
}

测试目标代码:HelloWorld.java

public class HelloWorld {

    private static final int TWENTY = 20;

    public boolean isAgeEquals20(Student student) {
        return student.getAge() == TWENTY;
    }
}

测试用例代码:HelloWorldTest.java

import com.bytedance.entity.Student;
import org.junit.Assert;
import org.junit.Test;
import org.powermock.api.mockito.PowerMockito;

public class HelloWorldTest {
    @Test
    public void testIsHelloWorld() {
        Student s = PowerMockito.mock(Student.class);
        try {
            HelloWorld hello = new HelloWorld();
            PowerMockito.when(s.getAge()).thenReturn(20);
            Assert.assertTrue(hello.isAgeEquals20(s));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
Mock 方法内部 new 出来的对象

测试目标代码:

public class HelloWorld {

    private static final int THIRTY = 30;

    public boolean isAgeEquals30(int age, String name) {
        Student student = new Student(age, name);
        return student.getAge() == THIRTY;
    }

}

测试用例代码:

import com.bytedance.entity.Student;
import org.junit.Assert;
import org.junit.Test;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;

public class HelloWorldTest {

    @Test
    @PrepareForTest(HelloWorld.class)
    public void testIsAgeEquals30() {
        Student s = PowerMockito.mock(Student.class);
        try {
            HelloWorld hello = new HelloWorld();
            PowerMockito.whenNew(Student.class).withArguments(30, "123").thenReturn(s);
            PowerMockito.when(s.getAge()).thenReturn(30);
            Assert.assertTrue(hello.isAgeEquals30(30, "123"));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

说明:当使用 PowerMockito.whenNew 方法时,必须加注解 @PrepareForTest 和 @RunWith。

注解 @PrepareForTest 里写的类是需要 mock 的 new 对象代码所在的类。

Mock 普通对象的 final 方法

测试目标代码:

public class ClassDependency {
    public final boolean isRight() {
        return true;
    }
}

public class Demo {
    public boolean callFinal(ClassDependency refer) {
        return refer.isRight();
    }
}

测试用例:

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)
public class DemoTest {

    @Test
    @PrepareForTest(ClassDependency.class)
    public void testCallFinal() {
        ClassDependency refer = PowerMockito.mock(ClassDependency.class);
        PowerMockito.when(refer.isRight()).thenReturn(false);
        Demo demo = new Demo();
        Assert.assertFalse(demo.callFinal(refer));
    }
}

说明:当需要 mock final 方法的时候,必须加注解 @PrepareForTest 和 @RunWith。

注解 @PrepareForTest 里写的类是 final 方法所在的类。

Mock 普通对象的静态方法、私有方法

操作与 Mock final 方法一致,不再演示。

踩坑指南

报错提示:

Also, this error might show up because:

  1. you stub either of: final/private/equals()/hashCode() methods. Those methods cannot be stubbed/verified. Mocking methods declared on non-public parent classes is not supported.
  2. inside when() you don’t call method on mock but on some other object.

根据提示我们知道,PowerMock 不可以 stub/verify final/private/equals()/hashCode() 方法。

某一踩坑代码如下所示:

HelloWorld.java

public class HelloWorld {

    public boolean isHelloWorld(String s) {
        return "Hello World!".equals(s);
    }

}

HelloWorldTest.java

import org.junit.Assert;
import org.junit.Test;
import org.powermock.api.mockito.PowerMockito;

public class HelloWorldTest {

    @Test
    public void testIsHelloWorld() {
        String s = PowerMockito.mock(String.class);
        HelloWorld hello = new HelloWorld();
        PowerMockito.when("Hello World!".equals(s)).thenReturn(true);
        Assert.assertTrue(hello.isHelloWorld(s));
    }

}

控制台错误提示:

org.mockito.exceptions.misusing.MissingMethodInvocationException:
when() requires an argument which has to be 'a method call on a mock'.
For example:
    when(mock.getArticles()).thenReturn(articles);

Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
   Those methods *cannot* be stubbed/verified.
   Mocking methods declared on non-public parent classes is not supported.
2. inside when() you don't call method on mock but on some other object.

  at com.bytedance.powermock.HelloWorldTest.testIsHelloWorld(HelloWorldTest.java:22)

防踩坑指南:

不能 Mock equals() 和 hashCode() 方法。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/349320.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号