Junit Mockito实现单元测试方法介绍

 更新时间:2022年09月19日 16:52:37   作者:π大星的日常  
JUnit是用于编写和运行可重复的自动化测试开源测试项目框架,这样可以保证我们的代码按与其工作。JUnit可广泛用于工业和作为支架(从命令行)或IDE(如IDE)内单独的java程序

一、前言

相信做过开发的同学,都多多少少写过下面的代码,很长一段时间我一直以为这就是单元测试...

@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 注解:

以下是一些常用的 Assert 断言:

三、Mockito 框架

从上面的介绍我们可以认识到,如何减少对外部的依赖才是实践单元测试的关键。而这正是Mockito的使命,Mockito 是一个流行的 mock 框架,可以与 JUnit 结合使用,Mockito 允许我们创建和配置 mock 对象,使用 Mockito 将大大简化了具有外部依赖项的类的测试开发。spring-boot-starter-test 中默认集成了 Mockito,不需要额外引入。

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

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

3.1 使用 Mockito 创建 mock 对象

Mockito 提供了几种创建 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 静态方法和私有方法。这个时候我们就要用到 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(""));
    }
}

到此这篇关于Junit Mockito实现单元测试方法介绍的文章就介绍到这了,更多相关Junit Mockito单元测试内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 面试官问如何启动Java 线程

    面试官问如何启动Java 线程

    这篇文章主要介绍了面试官问如何启动Java 线程,Java 的线程创建和启动非常简单,但如果问一个线程是怎么启动起来的往往并不清楚,甚至不知道为什么启动时是调用start(),而不是调用run()方法呢?下面我们就一起进入文章学习这个问题吧
    2021-12-12
  • SpringBoot 拦截器和自定义注解判断请求是否合法

    SpringBoot 拦截器和自定义注解判断请求是否合法

    这篇文章主要介绍了SpringBoot 拦截器和自定义注解判断请求是否合法,帮助大家更好的理解和使用springboot框架,感兴趣的朋友可以了解下
    2020-12-12
  • Java如何处理图片保存之后变红色的问题

    Java如何处理图片保存之后变红色的问题

    这篇文章主要介绍了Java如何处理图片保存之后变红色的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-11-11
  • IDEA一键完成格式化、去除无用引用、编译的操作

    IDEA一键完成格式化、去除无用引用、编译的操作

    这篇文章主要介绍了IDEA一键完成格式化、去除无用引用、编译的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • Java任务调度的常见实现方法与比较详解

    Java任务调度的常见实现方法与比较详解

    这篇文章主要介绍了Java任务调度的常见实现方法与比较,结合实例形式分析了Java任务调度的四种常见实现方法,使用区别及相关注意事项,需要的朋友可以参考下
    2017-08-08
  • JDK源码Enum类原理及代码实例解析

    JDK源码Enum类原理及代码实例解析

    这篇文章主要介绍了JDK源码Enum类原理及代码实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-11-11
  • SpringDataJpa创建联合索引的实现

    SpringDataJpa创建联合索引的实现

    这篇文章主要介绍了SpringDataJpa创建联合索引的实现,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-12-12
  • MyBatis 引入映射器的方法

    MyBatis 引入映射器的方法

    本文通过实例代码给大家分享mybatis 引入映射器的方法,非常不错,具有参考借鉴价值,需要的朋友参考下吧
    2017-09-09
  • 基于parameters参数实现参数化过程解析

    基于parameters参数实现参数化过程解析

    这篇文章主要介绍了基于parameters参数实现参数化过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-08-08
  • 复杂JSON字符串转换为Java嵌套对象的实现

    复杂JSON字符串转换为Java嵌套对象的实现

    这篇文章主要介绍了复杂JSON字符串转换为Java嵌套对象的实现,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-09-09

最新评论