IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发测试 -> 系统设计六-单元测试和Mock的应用 -> 正文阅读

[开发测试]系统设计六-单元测试和Mock的应用

单元测试知识

百度百科

单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证。对于单元测试中单元的含义,一般来说,要根据实际情况去判定其具体含义,如C语言中单元指一个函数,Java里单元指一个类,图形化的软件中可以指一个窗口或一个菜单等。总的来说,单元就是人为规定的最小的被测功能模块。单元测试是在软件开发过程中要进行的最低级别的测试活动,软件的独立单元将在与程序的其他部分相隔离的情况下进行测试。

POM依赖

SpringBoot 中的 pom.xml 文件需要添加的依赖

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.1</version>
        </dependency>        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

@runWith注解作用

注解描述
@RunWith就是一个运行器
@RunWith(JUnit4.class)就是指用JUnit4来运行
@RunWith(SpringJUnit4ClassRunner.class)让测试运行于Spring测试环 境,以便在测试开始的时候自动创建Spring的应用上下文
@RunWith(SpringRunner.class)SpringRunner extends SpringJUnit4ClassRunner
@RunWith(Suite.class)就是一套测试集合
@RunWith(MockitoJUnitRunner.class)使Mockito的注解生效

单元测试注解

注解描述
@Test使用该注解标注的public void方法会表示为一个测试方法
@BeforeClass表示在类中的任意public static void方法执行之前执行
@AfterClass表示在类中的任意public static void方法之后执行
@Before表示在任意使用@Test注解标注的public void方法执行之前执行
@After表示在任意使用@Test注解标注的public void方法执行之后执行

@SpringBootTest 注解作用

属性描述
Class<?>[] classes()指定启动类
SpringBootTest.WebEnvironment webEnvironment()
经常和测试类中@LocalServerPort一起在注入属性时使用。会随机生成一个端口号

@RunWith(JUnit4.class)使用

?定义计算类Calculate

import lombok.extern.slf4j.Slf4j;

/**
 * 计算类定义
 *
 * @author yangyanping
 * @date 2022-04-07
 */
@Slf4j
public class Calculate {

    /**
     * 加法
     */
    public int add(int a, int b) {
        log.info("{} add {}", a, b);
        return a + b;
    }

    /**
     * 减法
     */
    public int sub(int a, int b) {
        log.info("{} sub {}", a, b);
        return a - b;
    }

    /**
     * 乘法
     */
    public int mult(int a, int b) {
        log.info("{} mult {}", a, b);
        
        return a * b;
    }

    /**
     * 除法
     */
    public int dev(int a, int b) {
        log.info("{} dev {}", a, b);
        
        return a / b;
    }
}
@Slf4j
public class InjectCalculate {
    @Autowired
    private Calculate mockCalculate;

    public int add(int a, int b) {
        log.info("{} add {}", a, b);
        return mockCalculate.add(a, b);
    }
}

定义单元测试类CalculateTest

/**
 * 计算类单元测试类定义
 *
 * @author yangyanping
 * @date 2022-04-07
 */
@RunWith(JUnit4.class)
public class CalculateTest {

    private Calculate calculate;

    private int a;
    private int b;

    /**
     * 初始化方法
     */
    @Before
    public void init() {
        calculate = new Calculate();
        a = 10;
        b = 2;
    }

    /**
     * 加法
     */
    @Test
    public void testAdd() {
        Assert.assertEquals(12L, calculate.add(a, b));
    }

    /**
     * 减法
     */
    @Test
    public void testSub() {
        Assert.assertEquals(8L, calculate.sub(a, b));
    }

    /**
     * 乘法
     */
    @Test
    public void testMult() {
        Assert.assertEquals(20L, calculate.mult(a, b));
    }

    /**
     * 除法
     */
    @Test
    public void testDev() {
        Assert.assertEquals(5L, calculate.dev(a, b));
    }

    /**
     * 除法
     */
    @Test(expected = ArithmeticException.class)
    public void testDevException() {
        calculate.dev(a, 0);
    }
}

运行效果

Mock单元测试

Mock的概念

所谓的mock就是创建一个类的虚假的对象,在测试环境中,用来替换掉真实的对象,以达到两大目的:

  1. 验证这个对象的某些方法的调用情况,调用了多少次,参数是什么等等
  2. 指定这个对象的某些方法的行为,返回特定的值,或者是执行特定的动作

Mockito的注解生效

方式一:给被测类添加@RunWith(MockitoJUnitRunner.class)注解

/**
 * 计算类单元测试类定义
 *
 * @author yangyanping
 * @date 2022-04-07
 */
@Slf4j
@RunWith(MockitoJUnitRunner.class)
public class MockCalculateTest {
 }

方式二:在初始化方法中使用MockitoAnnotations.openMocks(MockCalculateTest.class)

    /**
     * 初始化方法
     */
    @BeforeClass
    public static void init() {
        MockitoAnnotations.openMocks(MockCalculateTest.class);
    }

@Mock 和 @Spy

注解描述
@Mock对函数的调用均执行mock(即虚假函数),不执行真正部分
@Spy对函数的调用均执行真正部分。Mockito中的Mock和Spy都可用于拦截那些尚未实现或不期望被真实调用的对象和方法,并为其设置自定义行为。二者的区别在于Mock不真实调用,Spy会真实调用。
@InjectMocks通过创建一个实例,它可以调用真实代码的方法,其余用@Mock(或@Spy)注解创建的mock将被注入到用该实例中

MockCalculateTest类定义

/**
 * 计算类单元测试类定义
 *
 * @author yangyanping
 * @date 2022-04-07
 */
@Slf4j
@RunWith(MockitoJUnitRunner.class)
public class MockCalculateTest {

    @Mock
    private static Calculate mockCalculate;

    @Spy
    private static Calculate spyCalculate;

    @InjectMocks
    private InjectCalculate injectCalculate;

    private int a = 10;
    private int b = 2;

    /**
     * 初始化方法
     */
    @BeforeClass
    public static void init() {
        MockitoAnnotations.openMocks(MockCalculateTest.class);
    }

    /**
     * 加法
     */
    @Test
    public void testAdd() {
        // 默认返回结果是返回类型int的默认值
        Assert.assertEquals(0, mockCalculate.add(a, b));
    }

    /**
     * 减法
     */
    @Test
    public void testSub() {
        // 默认会走真实方法
        Assert.assertEquals(8L, spyCalculate.sub(a, b));

        //打桩后,不会走了
        when(spyCalculate.sub(2, 1)).thenReturn(8);
        Assert.assertEquals(8L, spyCalculate.sub(2, 1));

        // 但是参数不匹配的调用,依然走真实方法
        Assert.assertEquals(1L, spyCalculate.sub(4, 3));
    }

    /**
     * 加法
     */
    @Test
    public void testInjectAdd() {
        when(mockCalculate.add(anyInt(), anyInt())).thenReturn(10);
        // 默认返回结果是返回类型int的默认值
        Assert.assertEquals(10, injectCalculate.add(2, 3));
    }
}

运行testAdd

结果没有日志:10?add 2 输出,即没有执行Calculate 类真实的add方法,

运行testSub

输出结果有运行日志,即执行了Calculate 类真实的sub方法

@RunWith(SpringRunner.class)

定义抽象基类

/**
 * 单元测试基础类
 *
 * @author yangyanping
 * @date 2022-04-07
 */
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest(classes = WebConfig.class)
public abstract class AbstractBootTest {

    @Before
    public void init() {
        log.info("Spring boot test is being started, please wait ....");
    }
}
WebConfig定义
/**
 * 系统配置类
 * @author yangyanping
 * @date 2021-08-25
 */
@EnableAsync
@EnableCaching
@MapperScan("com.flow.dao")
@EnableAspectJAutoProxy(proxyTargetClass = true)
@ImportResource("classpath:applicationContext-web.xml")
@SpringBootApplication(scanBasePackages = {"com.flow"}, exclude = {DataSourceAutoConfiguration.class})
public class WebConfig {
}
@Slf4j
public class FlowQueryProviderTest extends AbstractBootTest {

    @Autowired
    private FlowQueryProvider flowQueryProvider;

    @Test
    public void testQueryApproveNode(){
        ApproveNodeQuery query = new ApproveNodeQuery();
        query.setApproveErp("xiyangyang");
        query.setApproveStatus(FlowReqNodeStatus.ADOPT.getCode());

        FlowResult<PageResult<FlowReqNodeVo>> flowResult =         
        flowQueryProvider.queryApproveNode(query);

        Assert.assertNotNull(flowResult.getModel());
    }
}

  开发测试 最新文章
pytest系列——allure之生成测试报告(Wind
某大厂软件测试岗一面笔试题+二面问答题面试
iperf 学习笔记
关于Python中使用selenium八大定位方法
【软件测试】为什么提升不了?8年测试总结再
软件测试复习
PHP笔记-Smarty模板引擎的使用
C++Test使用入门
【Java】单元测试
Net core 3.x 获取客户端地址
上一篇文章      下一篇文章      查看所有文章
加:2022-04-15 00:30:46  更:2022-04-15 00:34:28 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/18 0:48:46-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码