TestNG + PowerMock 单元测试(上)

简介: 单元测试(Unit Testing),是指对软件或项目中最小可测试单元进行正确性检验的测试工作。单元是人为规定最小可测试的功能模块,可以是一个模块,一个函数或者一个类。单元测试需要与模块开发进行隔离情况下进行测试。

单元测试(Unit Testing),是指对软件或项目中最小可测试单元进行正确性检验的测试工作。单元是人为规定最小可测试的功能模块,可以是一个模块,一个函数或者一个类。单元测试需要与模块开发进行隔离情况下进行测试。


在程序开发完成后,我们往往不能保证程序 100% 的正确,通过单元测试的编写,我们可以通过自动化的测试程序将我们的输入输出程序进行定义,通过断言来 Check 各个 Case 的结果,检测我们的程序。以提高程序的正确性,稳定性,可靠性,节省程序开发时间。我们在项目中主要用到的单元测试框架有 Spring-Boot-Test TestNG、PowerMock 等。


TestNG,即 Testing, Next Generation,下一代测试技术,是一套根据 JUnit 和 NUnit 思想而构建的利用注释来强化测试功能的一个测试框架,即可以用来做单元测试,也可以用来做集成测试。


PowerMock 也是一个单元测试模拟框架,它是在其它单元测试模拟框架的基础上做出的扩展。通过提供定制的类加载器以及一些字节码篡改技巧的应用,PowerMock 现了对静态方法、构造方法、私有方法以及 Final 方法的模拟支持,对静态初始化过程的移除等强大的功能。


常用注解


1. TestNG  注解


  • @BeforeSuite 在该套件的所有测试都运行在注释的方法之前,仅运行一次


  • @AftereSuite  在该套件的所有测试都运行在注释方法之后,仅运行一次


  • @BeforeClass  在调用当前类的第一个测试方法之前运行,注释方法仅运行一次


  • @AftereClass  在调用当前类的第一个测试方法之后运行,注释方法仅运行一次


  • @BeforeMethod  注释方法将在每个测试方法之前运行


  • @AfterMethod   注释方法将在每个测试方法之后运行


  • @BeforeTest  注释的方法将在属于test标签内的类的所有测试方法运行之前运行


  • @AfterTest    注释的方法将在属于test标签内的类的所有测试方法运行之后运行


  • @DataProvider  标记一种方法来提供测试方法的数据。 注释方法必须返回一个

    Object [] [],其中每个Object []可以被分配给测试方法的参数列表。 要从该    DataProvider接收数据的@Test方法需要使用与此注释名称相等的dataProvider名称


  • @Parameters   描述如何将参数传递给@Test方法 ;适用于 xml 方式的参数化方式传值


  • @Test 将类或方法标记为测试的一部分,此标记若放在类上,则该类所有公共方法都将被作为测试方法


2. PowerMock 注解


  • @Mock  注解实际上是 Mockito.mock() 方法的缩写,我们只在测试类中使用它;


  • @InjectMocks 主动将已存在的 mock 对象注入到 bean 中, 按名称注入, 但注入失败不会抛出异常;


  • @Spy 封装一个真实的对象,以便可以像其他 mock 的对象一样追踪、设置对象的行为;


  • @PrepareForTest 对于静态方法,私有方法,final 方法,在用powermock做单元测试的时候,需要增加注解; 这个注解的作用就是:该注释告诉PowerMock(ito)列出的类将需要在字节码级别上进行操作。


示例代码


  1. 添加 pom.xml 依赖


以 Spring-Boot 项目为例,首先我们需要添加 TestNG + ProwerMock 依赖依赖如下:


<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.testng</groupId>
    <artifactId>testng</artifactId>
    <version>${testng.version}</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-api-mockito2</artifactId>
    <version>${powermock.version}</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-module-junit4</artifactId>
    <version>${powermock.version}</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-module-testng</artifactId>
    <version>${powermock.version}</version>
    <scope>test</scope>
</dependency>


  1. 增加单元测试


增加测试代码


import com.test.testng.dto.OrderDto;
import com.test.testng.dto.UserDto;
import org.mockito.*;
import org.powermock.modules.testng.PowerMockTestCase;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.when;
public class OrderServiceTest extends PowerMockTestCase {
    @BeforeMethod
    public void before() {
        MockitoAnnotations.openMocks(this);
    }
    @InjectMocks
    private OrderService orderService;
    @Mock
    private UserService userService;
    // 正常测试
    @Test
    public void testCreateOrder() {
        //1. mock method start
        UserDto userDto = new UserDto();
        userDto.setId(100);
        when(userService.get()).thenReturn(userDto);
        //2. call business method
        OrderDto order = orderService.createOrder(new OrderDto());
        //3. assert
        assertEquals(order.getId(), 100);
    }
    // 异常测试
    @Test
    public void testCreateOrderEx() {
        //1. mock method start
        when(userService.get()).thenThrow(new RuntimeException());
        Exception exception = null;
        try {
            //2. call business method
            orderService.createOrder(new OrderDto());
        } catch (RuntimeException e) {
            exception = e;
        }
        //3. assert
        assertNotNull(exception);
    }
}


常用 Mock 方式


1. Mock 静态方法


//静态方法
UserDto dto = new UserDto();
dto.setId(100000);
PowerMockito.mockStatic(UserService.class);
PowerMockito.when(UserService.loginStatic()).thenReturn(dto);
UserDto userDto = UserService.loginStatic();
assertEquals(100000, userDto.getId().intValue());


2. Mock 私有属性


//字段赋值
ReflectionTestUtils.setField(orderService, "rateLimit", 99);


3. Mock 私有方法


mock 私有方法需要注意需要增加 @PrepareForTest 注解


// 模拟私有方法
MemberModifier.stub(MemberMatcher.method(UserService.class, "get1")).toReturn(new UserDto());
// 测试私有方法
Method method = PowerMockito.method(UserService.class, "get1", Integer.class);
Object userDto = method.invoke(userService, 1);
assertTrue(userDto instanceof UserDto);


相关文章
|
1天前
|
XML Java 测试技术
TestNG 与 JUnit 测试框架:哪个更好?
【2月更文挑战第16天】
56 1
TestNG 与 JUnit 测试框架:哪个更好?
|
12月前
|
Java 测试技术 Maven
《Java单元测试实战》——基础知识:Java单元测试技巧之PowerMock(1)
《Java单元测试实战》——基础知识:Java单元测试技巧之PowerMock(1)
258 0
|
12月前
|
Java 测试技术
《Java单元测试实战》——基础知识:Java单元测试技巧之PowerMock(2)
《Java单元测试实战》——基础知识:Java单元测试技巧之PowerMock(2)
180 0
|
12月前
|
Java 测试技术
《Java单元测试实战》——基础知识:Java单元测试技巧之PowerMock(3)
《Java单元测试实战》——基础知识:Java单元测试技巧之PowerMock(3)
147 0
|
12月前
|
Java 测试技术
《Java单元测试实战》——基础知识:Java单元测试技巧之PowerMock(4)
《Java单元测试实战》——基础知识:Java单元测试技巧之PowerMock(4)
469 0
|
12月前
|
Java 测试技术
《Java单元测试实战》——基础知识:Java单元测试技巧之PowerMock(5)
《Java单元测试实战》——基础知识:Java单元测试技巧之PowerMock(5)
112 0
|
12月前
|
Java 测试技术
《Java单元测试实战》——基础知识:Java单元测试技巧之PowerMock(6)
《Java单元测试实战》——基础知识:Java单元测试技巧之PowerMock(6)
124 0
|
12月前
|
Java 测试技术
《Java单元测试实战》——基础知识:Java单元测试技巧之PowerMock(7)
《Java单元测试实战》——基础知识:Java单元测试技巧之PowerMock(7)
148 0
|
12月前
|
Java 测试技术
《Java单元测试实战》——基础知识:Java单元测试技巧之PowerMock(8)
《Java单元测试实战》——基础知识:Java单元测试技巧之PowerMock(8)
104 0
|
12月前
|
Java 测试技术
《Java单元测试实战》——基础知识:Java单元测试技巧之PowerMock(9)
《Java单元测试实战》——基础知识:Java单元测试技巧之PowerMock(9)
158 0

热门文章

最新文章