使用 Junit + Mockito 实践单元测试

简介:

使用 Junit + Mockito 实践单元测试
阅读目录

一、前言
二、JUnit 框架
三、Mockito 框架
回到顶部
一、前言
相信做过开发的同学,都多多少少写过下面的代码,很长一段时间我一直以为这就是单元测试...

@SpringBootTest
@RunWith(SpringRunner.class)
public class UnitTest1 {

@Autowired
private UnitService unitService;

@Test
public void test() {
    System.out.println("----------------------");
    System.out.println(unitService.sayHello());
    System.out.println("----------------------");
}

}
但这是单元测试嘛?unitService 中可能还依赖了 Dao 的操作;如果是微服务,可能还要起注册中心。那么这个“单元”也太大了吧!如果把它称为集成测试,可能更恰当一点,那么有没有可能最小粒度进行单元测试嘛?

单元测试应该是一个带有隔离性的功能测试。在单元测试中,应尽量避免其他类或系统的副作用影响。

单元测试的目标是一小段代码,例如方法或类。方法或类的外部依赖关系应从单元测试中移除,而改为测试框架创建的 mock 对象来替换依赖对象。

单元测试一般由开发人员编写,通过验证或断言目标的一些行为或状态来达到测试的目的。

回到顶部
二、JUnit 框架
JUnit 是一个测试框架,它使用注解来标识测试方法。JUnit 是 Github 上托管的一个开源项目。

一个 JUnit 测试指的是一个包含在测试类中的方法,要定义某个方法为测试方法,请使用 @Test 注解标注该方法。该方法执行被测代码,可以使用 JUnit 或另一个 Assert 框架提供的 assert 方法来检查预期结果与实际结果是否一致,这些方法调用通常称为断言或断言语句。

public class UnitTest2 {

@Test
public void test() {
    String sayHello = "Hello World";
    Assert.assertEquals("Hello World", sayHello);
}

}
以下是一些常用的 JUnit 注解:

注解 描述
@Test 将方法标识为测试方法
@Before 在每次测试之前执行。用于准备测试环境(例如,读取输入数据,初始化类)
@After 每次测试之后执行。用于清理测试环境(例如,删除临时数据,恢复默认值)
@BeforeClass 用于 static方法,在所有测试开始之前执行一次。它用于执行耗时的活动,例如:连接到数据库
@AfterClass 用于 static方法,在完成所有测试之后,执行一次。它用于执行清理活动,例如:与数据库断开连接
@Ignore 指定要忽略的测试
@Test(expected = Exception.class) 如果该方法未引发命名异常,则失败
@Test(timeout=100) 如果该方法花费的时间超过100毫秒,则失败
以下是一些常用的 Assert 断言:

声明 描述
fail([message]) 使方法失败。在执行测试代码之前,可用于检查未到达代码的特定部分或测试失败
assertTrue([message,]布尔条件) 检查布尔条件是否为真
assertFalse([message,]布尔条件) 检查布尔条件是否为假
assertEquals([message,]预期,实际) 测试两个值是否相同。注意:对于数组,会检查引用而不是数组的内容
assertNull([message,]对象) 检查对象是否为空
assertNotNull([message,]对象) 检查对象是否不为空
assertSame([message,]预期,实际) 检查两个变量是否引用同一对象
assertNotSame([message,]预期,实际) 检查两个变量是否引用了不同的对象
回到顶部
三、Mockito 框架
从上面的介绍我们可以认识到,如何减少对外部的依赖才是实践单元测试的关键。而这正是 Mockito 的使命,Mockito 是一个流行的 mock 框架,可以与 JUnit 结合使用,Mockito 允许我们创建和配置 mock 对象,使用 Mockito 将大大简化了具有外部依赖项的类的测试开发。spring-boot-starter-test 中默认集成了 Mockito,不需要额外引入。

在测试中使用 Mockito,通常会:

mock 外部依赖关系并将 mock 对象插入待测代码
执行被测代码
验证代码是否正确执行

3.1 使用 Mockito 创建 mock 对象
Mockit o提供了几种创建 mock 对象的方法:

使用静态 mock() 方法
使用 @Mock 注解
如果使用 @Mock 注解,则必须触发创建带有 @Mock 注解的对象。使用 MockitoRule 可以做到,它通过调用静态方法 MockitoAnnotations.initMocks(this) 来填充带 @Mock 注解的字段。或者可以使用 @RunWith(MockitoJUnitRunner.class)。

public class UnitTest3 {

// 触发创建带有 @Mock 注解的对象
@Rule public MockitoRule mockitoRule = MockitoJUnit.rule();
// 1. 使用 @Mock 注解创建 mock 对象
@Mock private UnitDao unitDao;

@Test
public void test() {
    // 2. 使用静态 mock() 方法创建 mock 对象
    Iterator iterator = mock(Iterator.class);
    // when...thenReturn / doReturn...when 模拟依赖调用
    when(iterator.next()).thenReturn("hello");
    doReturn(1).when(unitDao).delete(anyLong());
    // 断言
    Assert.assertEquals("hello", iterator.next());
    Assert.assertEquals(new Integer(1), unitDao.delete(1L));
}

}
3.2 使用 mock 对象实践单元测试
我们要单元测试的内容,常常包含着对数据库的访问等等,那么我们要如何 mock 掉这部分调用呢?我们可以使用 @InjectMocks 注解创建实例并使用 mock 对象进行依赖注入。

@Service
public class UnitServiceImpl implements UnitService {

@Autowired
private UnitDao unitDao;

@Override
public String sayHello() {
    Integer delete = unitDao.delete(1L);
    System.out.println(delete);
    return "hello unit";
}

}
@RunWith(MockitoJUnitRunner.class)
public class UnitTest2 {


@Mock
private UnitDao unitDao;
@InjectMocks
private UnitServiceImpl unitService;

@Test
public void unitTest() {
    // mock 调用
    when(unitDao.delete(anyLong())).thenReturn(1);
    Assert.assertEquals("hello unit", unitService.sayHello());
}

}
Mockito 还有很多有趣的实践,比如:@Spy或spy()方法、verify()验证等等,鉴于篇幅原因,读者可自行挖掘。

3.3 使用 PowerMock mock 静态方法。
Mockito 也有一些局限性。例如:不能 mock 静态方法和私有方法。有关详细信息,请参阅 Mockito限制的常见问题解答。这个时候我们就要用到 PowerMock,PowerMock 支持 JUnit 和 TestNG,扩展了 EasyMock 和 Mockito 框架,增加了mock static、final 方法的功能。

首先需要引入 PowerMock 的依赖:

    <!-- PowerMock -->
    <dependency>
        <groupId>org.powermock</groupId>
        <artifactId>powermock-module-junit4</artifactId>
        <version>2.0.7</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.powermock</groupId>
        <artifactId>powermock-api-mockito2</artifactId>
        <version>2.0.7</version>
    </dependency>

接下来就能愉快的 mock 静态方法了。

@RunWith(PowerMockRunner.class)
@PrepareForTest({StringUtils.class})
public class UnitTest4 {

@Test
public void test() {
    mockStatic(StringUtils.class);
    when(StringUtils.getFilename(anyString())).thenReturn("localhost");
    Assert.assertEquals("localhost", StringUtils.getFilename(""));
}

}

原文地址https://www.cnblogs.com/jmcui/p/12802099.html

相关文章
|
1月前
|
数据采集 监控 机器人
浅谈网页端IM技术及相关测试方法实践(包括WebSocket性能测试)
最开始转转的客服系统体系如IM、工单以及机器人等都是使用第三方的产品。但第三方产品对于转转的业务,以及客服的效率等都产生了诸多限制,所以我们决定自研替换第三方系统。下面主要分享一下网页端IM技术及相关测试方法,我们先从了解IM系统和WebSocket开始。
47 4
|
1月前
|
人工智能 JavaScript 前端开发
自动化测试框架的演进与实践###
本文深入探讨了自动化测试框架从诞生至今的发展历程,重点分析了当前主流框架的优势与局限性,并结合实际案例,阐述了如何根据项目需求选择合适的自动化测试策略。文章还展望了未来自动化测试领域的技术趋势,为读者提供了宝贵的实践经验和前瞻性思考。 ###
|
1月前
|
测试技术 Python
探索软件测试的深度与广度:从理论到实践
在数字化时代,软件已成为我们生活中不可或缺的一部分。随着技术的不断进步和用户需求的多样化,确保软件质量变得尤为重要。本文将深入浅出地介绍软件测试的核心概念、类型及其在软件开发生命周期中的重要性。我们将通过实际案例,展示如何实施有效的测试策略,并探讨自动化测试的未来趋势,旨在为读者提供一套完整的软件测试知识体系,帮助提升软件质量和开发效率。
|
1月前
|
测试技术 Python
探索软件测试的奥秘:从理论到实践
在软件开发的宇宙中,软件测试犹如一颗璀璨的星辰,指引着质量的方向。本文将带你穿梭于软件测试的理论与实践之间,揭示其内在的逻辑和魅力。从测试的重要性出发,我们将探讨不同类型的测试方法,并通过实际案例分析,深入理解测试用例的设计和应用。最后,我们将通过一个代码示例,展示如何将理论知识转化为实际操作,确保软件质量的同时,也提升你的测试技能。让我们一起踏上这段探索之旅,发现软件测试的无限可能。
|
1月前
|
jenkins 测试技术 持续交付
自动化测试框架的搭建与实践
在软件开发领域,自动化测试是提升开发效率、确保软件质量的关键手段。本文将引导读者理解自动化测试的重要性,并介绍如何搭建一个基本的自动化测试框架。通过具体示例和步骤,我们将探索如何有效实施自动化测试策略,以实现软件开发流程的优化。
70 7
|
1月前
|
测试技术
探索软件测试的奥秘:从理论到实践
本文深入探讨了软件测试的基本概念、重要性、主要类型以及实施策略。通过分析不同测试阶段和相应的测试方法,文章旨在为读者提供一套完整的软件测试知识体系,帮助他们更好地理解和应用测试技术,确保软件产品的质量和可靠性。
65 4
|
2月前
|
存储 算法 C语言
用C语言开发游戏的实践过程,包括选择游戏类型、设计游戏框架、实现图形界面、游戏逻辑、调整游戏难度、添加音效音乐、性能优化、测试调试等内容
本文探讨了用C语言开发游戏的实践过程,包括选择游戏类型、设计游戏框架、实现图形界面、游戏逻辑、调整游戏难度、添加音效音乐、性能优化、测试调试等内容,旨在为开发者提供全面的指导和灵感。
53 2
|
2月前
|
数据可视化 测试技术 API
软件测试中的自动化测试框架选择与实践
在当今快节奏的软件开发环境中,自动化测试成为了确保软件质量和加速交付的关键。本文将探讨自动化测试的重要性,并比较几种流行的自动化测试框架,包括Selenium、Appium和TestComplete。文章还将提供一些最佳实践和案例研究,以帮助读者更好地理解和实施自动化测试策略。
|
30天前
|
监控 搜索推荐 测试技术
电商API的测试与用途:深度解析与实践
在电子商务蓬勃发展的今天,电商API成为连接电商平台、商家、消费者和第三方开发者的重要桥梁。本文深入探讨了电商API的核心功能,包括订单管理、商品管理、用户管理、支付管理和物流管理,并介绍了有效的测试技巧,如理解API文档、设计测试用例、搭建测试环境、自动化测试、压力测试、安全性测试等。文章还详细阐述了电商API的多样化用途,如商品信息获取、订单管理自动化、用户数据管理、库存同步、物流跟踪、支付处理、促销活动管理、评价管理、数据报告和分析、扩展平台功能及跨境电商等,旨在为开发者和电商平台提供有益的参考。
38 0
|
2月前
|
人工智能 数据管理 jenkins
探索软件测试中的自动化框架:从基础到高级实践
在当今快速发展的软件行业中,自动化测试已成为提高开发效率和保障产品质量的关键手段。本文将深入探讨软件测试自动化的各个方面,包括其重要性、主流的自动化测试框架、以及如何有效地实施自动化测试策略。我们还将通过案例分析,展示自动化测试在实际项目中的应用效果,以及面临的挑战和解决方案。无论是软件开发者还是测试工程师,了解并掌握自动化测试技术都将极大提升工作效率和产品质量。
51 0