一、前言

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

@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单元测试内容请搜索Devmax以前的文章或继续浏览下面的相关文章希望大家以后多多支持Devmax!

Junit Mockito实现单元测试方法介绍的更多相关文章

  1. 如何通过代码设置iOS的系统时区?

    我想通过代码在iOS中设置系统时区,日期时间.任何想法或私人api帮助我?示例:将时区设置为GMT8,将日期时间设置为2013年8月10日晚上8:30.怎么做?

  2. ios – 如何为NSNotification编写单元测试

    我在swift工作,我想刷新一个页面,所以我使用通知发送它,我在一个ViewController中发布通知并在另一个中添加观察者,它工作正常.我想要做的是在swift中添加单元测试.我查了很多网站但是没能做到.我是新手,不知道从哪里开始.基本上工作是,当我点击按钮通知被发布时,并且当加载下一个视图控制器时,添加通知观察者.我该怎么做单元测试提前致谢编辑:码并添加观察者解决方法一般的解决方案是:使用

  3. 如何在iOS中为预期的assert / assertionFailure编写单元测试?

    这里的问题是,当someString参数为空字符串时,您可以保证函数不会失败–在您的实际应用程序中.这是因为断言不在发布版本中运行.结果是你可以在开发过程中使用assert作为调试的一种形式,但如果这种情况在现实生活中发生,你应该按顺序处理它,而不是崩溃.因此测试断言“发生”是否真的不是一种有效的单元测试技术,这就是为什么你以这种方式使用它的麻烦.

  4. xcode – 如何在不影响单元测试目标构建的情况下更改发布目标的名称?

    我有一个发布目标和一个测试目标,我想更改发布目标的名称,但如果我这样做,我开始在测试目标中获得链接错误.由于它们是单元测试,我认为在测试目标中不会/应该是对发布目标的依赖,但显然存在.链接错误是:在重命名之前,XYZ.app是发布目标的名称.是否有自动或快速更新单元测试目标的方法,以便它保持步调状态?

  5. ios – 可以测试IBAction吗?

    对IBOutlets进行单元测试有点容易,但IBActions呢?我试图找到一种方法,但没有任何运气.有没有办法在ViewController中的IBAction和nib文件中的按钮之间进行单元测试连接?解决方法对于完整的单元测试,每个插座/操作需要三个测试:>插座是否连接到视野?

  6. ios app如何“知道”运行单元测试

    我知道我可以用xcodebuild开始我的应用程序的单元测试,但我想知道是什么告诉应用程序在启动期间运行测试,它是一个发送到应用程序的特殊参数,还是以不同的方式编译以运行测试?

  7. ios – Xcode 6.1直到运行时才检测到单元测试

    我遇到了Xcode6.1.1没有检测到单元测试文件的问题.我运行了与之关联的方案,并在运行时找到了该文件,最后在单元测试导航器中找到了一个“rT”图标.这导致我到thisquestion,但没有一个答案对我有用.删除我的派生数据或重新启动Xcode没有任何帮助.接近工作的唯一事情是在Xcode运行时删除我的派生数据文件夹–当它重新编制索引时,它发现了我的三个方案中的一个中的所有测试文件.所有这些测

  8. xcode – 在仪器中运行SenTestingKit单元测试

    我正在开发一个数据库访问库,我试图使用已经写的单元测试检查内存泄漏.这些是基于SenTestingKit的逻辑测试,在Xcode4.2中设置了正常的方式.我可以使用Cmd-U运行它们,但是没有看到从仪器启动它们的方法,或者调用仪器来检查它们.我该怎么做这个工作?我需要编写新的案例并将其构建到应用程序中吗?

  9. Xcode:用于条件DEBUG / TEST代码的预处理器宏

    我在我的代码(例如AppDelegate.m)中有不应该为单元测试编译的部分,例如当您在创建新项目时选择“添加单元测试”时,目标是由Xcode设置的.在项目文件中,我已将标志CONfigURATION_TESTS添加到内置目标的MyAppTests的预处理器宏中,但未添加到MyApp目标.这是我发现的许多帖子中的建议方式.但是这不起作用,因为(我猜)MyAppTests目标将MyApp目标作为依赖

  10. xcode – 如何将Compile Sources中的文件从一个目标复制并粘贴到另一个目标?

    我有一个主要目标,其目标下包含某些文件–>构建阶段–>编译源我开始单元测试,并希望单元测试包含与主要目标相同的文件.有没有办法将包含在一个目标中的文件复制粘贴到另一个目标?

随机推荐

  1. 基于EJB技术的商务预订系统的开发

    用EJB结构开发的应用程序是可伸缩的、事务型的、多用户安全的。总的来说,EJB是一个组件事务监控的标准服务器端的组件模型。基于EJB技术的系统结构模型EJB结构是一个服务端组件结构,是一个层次性结构,其结构模型如图1所示。图2:商务预订系统的构架EntityBean是为了现实世界的对象建造的模型,这些对象通常是数据库的一些持久记录。

  2. Java利用POI实现导入导出Excel表格

    这篇文章主要为大家详细介绍了Java利用POI实现导入导出Excel表格,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  3. Mybatis分页插件PageHelper手写实现示例

    这篇文章主要为大家介绍了Mybatis分页插件PageHelper手写实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  4. (jsp/html)网页上嵌入播放器(常用播放器代码整理)

    网页上嵌入播放器,只要在HTML上添加以上代码就OK了,下面整理了一些常用的播放器代码,总有一款适合你,感兴趣的朋友可以参考下哈,希望对你有所帮助

  5. Java 阻塞队列BlockingQueue详解

    本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景,通过实例代码介绍了Java 阻塞队列BlockingQueue的相关知识,需要的朋友可以参考下

  6. Java异常Exception详细讲解

    异常就是不正常,比如当我们身体出现了异常我们会根据身体情况选择喝开水、吃药、看病、等 异常处理方法。 java异常处理机制是我们java语言使用异常处理机制为程序提供了错误处理的能力,程序出现的错误,程序可以安全的退出,以保证程序正常的运行等

  7. Java Bean 作用域及它的几种类型介绍

    这篇文章主要介绍了Java Bean作用域及它的几种类型介绍,Spring框架作为一个管理Bean的IoC容器,那么Bean自然是Spring中的重要资源了,那Bean的作用域又是什么,接下来我们一起进入文章详细学习吧

  8. 面试突击之跨域问题的解决方案详解

    跨域问题本质是浏览器的一种保护机制,它的初衷是为了保证用户的安全,防止恶意网站窃取数据。那怎么解决这个问题呢?接下来我们一起来看

  9. Mybatis-Plus接口BaseMapper与Services使用详解

    这篇文章主要为大家介绍了Mybatis-Plus接口BaseMapper与Services使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  10. mybatis-plus雪花算法增强idworker的实现

    今天聊聊在mybatis-plus中引入分布式ID生成框架idworker,进一步增强实现生成分布式唯一ID,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

返回
顶部