单元测试框架TestNG、Mockito、Unitils-Spring及示例

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_32250495/article/details/82723705
一. TestNG  对Junit的扩展可通过xml脚本同时运行多个case
TestNG运行时将经过一下几个阶段:
1. 类级初始化资源处理        @BeforeClass注解标记
2. 方法级别初始化资源处理    @BeforeMethod
3. 执行测试用例中的方法      @Test
4. 方法级别的销毁          @AfterMethod
5. 类级别的销毁           @AfterClass
如果定义了多个初始化方法,先执行定义在最后面的,而销毁方法先执行定义在最前面的。
如果定义多个@Test的用例,会为每个@Test方法生成一个测试用例实例分别运行。
@BeforeClas @AfterClass在一个测试用例实例中只运行一次。

测试方法: 通过@Test标注方法执行一个测试逻辑,然后通过Assert进行断言。
详细实例请见:com.test.TestNGLearn

二. Mockito
Mockito只适用于对Service层的方法进行单元测试
Mockito可以mock某些类和方法的执行,设定某些期望的行为和返回值
常用来测试判定逻辑等,通过mock避免执行某些依赖的逻辑

Mockito + Assert 可以方便的测试服务类的逻辑结构。

详细实例请见:com.test.MockitoLearn

三. Unitils
专用于测试框架整合, 通过配置文件开启模块功能。unitils定义了Module接口,通过实现这个接口整合其他框架,同时也可以自定义。
1. ReflectionAssert反射断言 详细实例见: com.test.UnitilsLearn
2. 集成Spring               详细实例见:com.test.UnitilsSpring
3. 集成Hibernate
4. 集成DBUtil
5. 对web层测试

TestNG示例:

package com.test;


import org.testng.annotations.*;

// 用于指定类属于的分组
// @Test(groups = {"group1"})
public class TestNGLearn {

    @BeforeClass
    public static void init(){
        System.out.println("类初始化");
    }

    @AfterClass
    public static void destroy(){
        System.out.println("类销毁");
    }

    @BeforeMethod
    public void initMethod(){
        System.out.println("用例执行初始化");
    }

    @Test
    public void testTestNG(){
        System.out.println("一个简单的测试");
    }

    // 开启异常测试,如果没有抛出指定的异常则测试失败。
    @Test(enabled = true , expectedExceptions = RuntimeException.class)
    public void testException(){
        throw new RuntimeException();
    }

    // 如果在timeOut指定的毫秒时间内未完成则测试失败
    @Test(enabled = true, timeOut = 2000)
    public void testTimeOut() throws InterruptedException{
        Thread.sleep(2000);
    }

    // 参数化测试,直接提供批量的测试参数,不必为每个参数写测试用例
    @DataProvider(name = "testParam")
    public static Object[][] getParameters(){
        String [][] params = {{"第一组第一个参数","第一组第二个参数"},{"第二组第一个参数","第二组第二个参数"}};
        return params;
    }
    // 通过一个二维数组,指定多组参数,每组可指定多个参数。
    @Test(dataProvider = "testParam")
    public void testBatchParam(String first , String second){
           System.out.println(first + " " +second);
    }

    // 分组测试, 每个测试方法单独生成实例,并都执行@BeforeMethod,而@BeforeClass之执行一次
    @Test(groups = {"group1"})
    public void testGroup2(){
        System.out.println("分组测试 group1分组的第1个测试用例");
    }

    @Test(groups = {"group1","group2"})
    public void testGroup1_1(){
        System.out.println("分组测试 group2分组的第1个测试用例");
    }

    @Test(groups = {"group2"})
    public void testGroup1_2(){
        System.out.println("分组测试 group2分组的第2个测试用例");
    }


    // 依赖测试
    @Test
    public void testDepond(){
        System.out.println("这是一个被依赖的方法");
    }

    @Test(dependsOnMethods = "testDepond")
    public void testDepond2(){
        System.out.println("前面一个方法执行成功,我才执行");
    }

    @AfterMethod
    public void destroyMethod(){
        System.out.println("用例执行收尾");
    }
}

TestNG脚本方式运行: 直接右键这个xml文件运行

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >

<!--配置只要指定某个包,某个类,某个方法,某个组即可运行-->

<!--定义一个测试套件 指定脚本名称以进行套件区分-->
<suite name="test_suite_1">
    <!--定义一个测试用例,suite脚本会运行每个测试用例-->
    <test name="group1_test" >
        <!--分组测试-->
        <groups>
            <!--群组: 将注解指定的分组,再次进行组合-->
            <define name="all">
                <include name="group1"/>
                <include name="gourp2"/>
            </define>


            <!--指定运行的组和不运行的组-->
            <run>
                <include name = "group2" />
            </run>
        </groups>

        <!--选择一个包中的全部@Test方法-->
        <packages>
            <package name = "com.test">
            </package>
        </packages>
    </test>

    <!--第二个测试用例-->
    <test name="group2_test">

        <!--运行指定某个类中的指定方法-->
        <classes>
            <class name="com.test.TestNGLearn">
                <methods>
                    <include name="testBatchParam"/>
                </methods>
            </class>
        </classes>
    </test>
</suite>

Mokito示例:

package com.test;

import com.learn.aop.business.SayHello;
import com.learn.aop.business.SayHi;
import com.learn.mvc.domains.User;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import static org.mockito.Mockito.*;

/**
 * mokito只适用于对Service层的方法进行单元测试
 * mokito可以mock某些类和方法的执行,设定某些期望的行为和返回值
 * 常用来测试判定逻辑等,通过mock避免执行某些依赖的逻辑
 *
 * Mockito + Assert 可以方便的测试服务类的逻辑结构。
 */
public class MockitoLearn {

    private static User user;
    // 注解mock
    @Mock
    SayHi sayHi;

    private SayHello sayHello;

    @BeforeClass
    public void intiClass(){
        // 开启注解
        MockitoAnnotations.initMocks(this);
    }

    @BeforeMethod
    public void initUser(){
        User user =new User();
        user.setId(3);
        user.setAge(18);
        user.setName("asdfe");
        user.setSex("female");
    }
    // 第一种mock方法
    @Test
    public void testMokito(){
        // 调用方法mock产生一个虚拟的服务类
        sayHello=mock(SayHello.class);

        User user=new User();
        doReturn(user).when(sayHello.myUser());

        Assert.assertNotNull(user);
    }

    // 第二中mock方法
    @Test
    public void testMokito2(){

        when(sayHi.getUser()).thenReturn(user);
        User user = sayHi.getUser();

        Assert.assertNotNull(user);
        System.out.println(user.getName());
    }

    // mockito的交互验证。
    // mockito能记录某个方法的执行次数。
    @Test
    public void testMockito3(){
        // 注解生成的sayHi mock类
        when(sayHi.getUser()).thenReturn(user);
        // 代码生成的sayHello mock类
        sayHello=mock(SayHello.class);

        // 验证其是否执行
        verify(sayHi).getUser();

        // 验证某个类某个方法的执行次数
        verify(sayHi,atLeast(1)).getUser();

        verify(sayHello,atLeastOnce()).myUser();
        verify(sayHello,atMost(1)).myUser();
    }
}

Unitils 反射断言

package com.test;

import com.learn.mvc.domains.User;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import org.unitils.reflectionassert.ReflectionAssert;
import org.unitils.reflectionassert.ReflectionComparatorMode;

// 测试反射断言
public class UnitilsLearn {
    private static User user1;
    private static User user2;
    private static User user3;

    @BeforeMethod
    public void initUser() {
        user1 = new User();
        user1.setName("vvvasd");
        user2 = new User();
        user3 = new User();
    }

    // 反射断言,判断两个实例是否相等,此处应该不相等,所以测试不通过。
    @Test
    public void testReflection() {
        ReflectionAssert.assertReflectionEquals(user1, user3);

    }

    // 反射断言,判断两个实例是否相等
    @Test
    public void testReflection2() {
        ReflectionAssert.assertReflectionEquals(user3, user2);

    }

    // 集合的比较 三种类型: 忽略顺序,忽略默认值,判断是否有值
    @Test
    public void testReflection3() {
        Integer orderList1[] = new Integer[]{1, 2, 3};
        Integer orderList2[] = new Integer[]{3, 2, 1};

        // 忽略顺序
        ReflectionAssert.assertReflectionEquals(orderList1,orderList1, ReflectionComparatorMode.LENIENT_ORDER);
        // 忽略默认值
        ReflectionAssert.assertReflectionEquals(orderList1,orderList1, ReflectionComparatorMode.IGNORE_DEFAULTS);
        // 对日期类型只判断是否有值
        ReflectionAssert.assertReflectionEquals(orderList1,orderList1, ReflectionComparatorMode.LENIENT_DATES);
    }

    // 断言一个POJO类中的属性是否为某个值
    @Test
    public void testPropertyEqual(){
        User user =new User();
        user.setName("hello");
        // Lenient模式忽略顺序和默认值。
        ReflectionAssert.assertPropertyLenientEquals("name","hello",user);
    }
}

Unitils 整合spring   注意:unitils默认的启动配置中,springModule必须在databaseModule之后启动,所以如果没有配置,database数据源将导致测试运行失败。可以自定义一个unitils.property文件配置启动方式

自定义配置文件如下: 直接复制了默认的配置文件:修改

unitils.module.spring.className=org.unitils.spring.SpringModule
unitils.module.spring.runAfter=database
unitils.module.spring.enabled=true

对于unitils.module.spring.runAfter属性,将database去掉变为:unitils.module.spring.runAfter=   


unitils.modules=database,dbunit,hibernate,mock,easymock,inject,spring,jpa,io

#### Unitils core configuration ###
# For each module, the implementation class is listed in unitils.module.<modulename>.className, the sequence of the
# execution of their code is influenced by unitils.module.<modulename>.runAfter. Disabling a module can be performed by
# setting unitils.module.<modulename>.enabled to false.
unitils.module.database.className=org.unitils.database.DatabaseModule
unitils.module.database.runAfter=
unitils.module.database.enabled=false

unitils.module.hibernate.className=org.unitils.orm.hibernate.HibernateModule
unitils.module.hibernate.runAfter=
unitils.module.hibernate.enabled=false

unitils.module.dbunit.className=org.unitils.dbunit.DbUnitModule
unitils.module.dbunit.runAfter=
unitils.module.dbunit.enabled=false

unitils.module.mock.className=org.unitils.mock.MockModule
unitils.module.mock.runAfter=
unitils.module.mock.enabled=false

unitils.module.easymock.className=org.unitils.easymock.EasyMockModule
unitils.module.easymock.runAfter=
unitils.module.easymock.enabled=false

unitils.module.inject.className=org.unitils.inject.InjectModule
unitils.module.inject.runAfter=
unitils.module.inject.enabled=false

unitils.module.spring.className=org.unitils.spring.SpringModule
unitils.module.spring.runAfter=
unitils.module.spring.enabled=true

unitils.module.jpa.className=org.unitils.orm.jpa.JpaModule
unitils.module.jpa.runAfter=
unitils.module.jpa.enabled=false

unitils.module.io.className=org.unitils.io.IOModule
unitils.module.io.runAfter=
unitils.module.io.enabled=false
package com.test;

import com.learn.aop.business.SayHello;
import org.junit.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import org.unitils.UnitilsTestNG;
import org.unitils.spring.annotation.SpringApplicationContext;
import org.unitils.spring.annotation.SpringBean;
import org.unitils.spring.annotation.SpringBeanByType;

/**
 * 注意一定要集成UnitilsTestNG类
 * unitils 启动会开启springModule然后初始化spring容器。
 * Unitils TestNG一定要一个数据源才能启动
 */

@SpringApplicationContext({"spring-servlet.xml"})
public class UnitilsSpring extends UnitilsTestNG {


    @SpringBean("sayHelloTarget")
    public SayHello sayHello;


//    @SpringBeanByName
//    public SayHello sayHello2;

    @SpringBeanByType
    public SayHello sayHello3;

    @BeforeMethod
    public void before() {
        System.out.println("开始准备");
    }

    @AfterMethod
    public void after() {
        System.out.println("运行结束");
    }

    // 测试手动启动
//    @Test
//    public void testSpring() {
//        ApplicationContext context = new ClassPathXmlApplicationContext("spring-test.xml");
//        sayHello2 = (SayHello) context.getBean("sayHello");
//        Assert.assertNotNull(sayHello2);
//    }

    // 测试注解启动
    @Test
    public void testSpring2() {
        sayHello.sayHello();
        Assert.assertNotNull(sayHello);
    }

    // 测试注解启动
    @Test
    public void testSpring3() {
        sayHello3.sayHello();
        Assert.assertNotNull(sayHello3);
    }

}

最后附上导入的包

 <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>6.14.3</version>
            <scope>test</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.mockito/mockito-core -->
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-core</artifactId>
            <version>2.21.0</version>
            <scope>test</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.unitils/unitils-core -->
        <dependency>
            <groupId>org.unitils</groupId>
            <artifactId>unitils-core</artifactId>
            <version>3.4.2</version>
            <scope>test</scope>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.unitils/unitils-spring -->
        <dependency>
            <groupId>org.unitils</groupId>
            <artifactId>unitils-spring</artifactId>
            <version>3.4.6</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.unitils/unitils-testng -->
        <dependency>
            <groupId>org.unitils</groupId>
            <artifactId>unitils-testng</artifactId>
            <version>3.3</version>
        </dependency>

猜你喜欢

转载自blog.csdn.net/qq_32250495/article/details/82723705