Mockito 调用模拟对象全解析

这篇具有很好参考价值的文章主要介绍了Mockito 调用模拟对象全解析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一个人最大的缺点,不是自私、多情、野蛮、任性,而是偏执地爱一个不爱自己的人

Spring Boot框架来编写一个简单的示例,演示如何使用DI框架在单元测试中使用Mock实现,避免对外部环境的依赖。

首先,我们创建一个UserService接口,定义了一个getUserById方法用于查询用户信息:

public interface UserService {
    User getUserById(long userId);
}

接着,我们创建一个UserServiceImpl实现类,实现了getUserById方法:

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;

    @Override
    public User getUserById(long userId) {
        return userDao.getUserById(userId);
    }
}

在这个实现类中,我们注入了一个UserDao对象,用于从数据库中查询用户信息。这里我们假设UserDao已经实现并可用。

现在,我们需要编写一个单元测试来测试getUserById方法。由于这个方法依赖于UserDao对象,为了避免对外部环境的依赖,我们可以使用Mockito框架来模拟UserDao对象的行为。

以下是使用Mockito框架编写的单元测试代码:

@RunWith(SpringRunner.class)
public class UserServiceTest {

    @MockBean
    private UserDao userDao;

    @Autowired
    private UserService userService;

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void testGetUserById() {
        User mockUser = new User();
        mockUser.setId(1L);
        mockUser.setUsername("test");
        mockUser.setPassword("test");
        Mockito.when(userDao.getUserById(1L)).thenReturn(mockUser);

        User user = userService.getUserById(1L);
        Assert.assertEquals("test", user.getUsername());
        Assert.assertEquals("test", user.getPassword());
    }
}

在这个测试中,我们使用@MockBean注解来注入一个Mock的UserDao对象,并使用Mockito.when方法模拟getUserById方法的行为。这样,在测试中就可以使用MockUserDao对象,而不需要依赖于外部环境。

通过这种方式,我们可以编写稳健、可靠的单元测试,并将其纳入持续集成系统中进行自动化测试,提高软件的质量和稳定性。同时,我们也能避免对外部环境的依赖,保证单元测试的独立性和可重复性。

关键代码分析

MockitoAnnotations.initMocks(this)

MockitoAnnotations.initMocks(this)方法并不会产生代理类,它主要是用于初始化Mockito注解。在测试中,我们通常使用@Mock、@Spy、@InjectMocks等注解来创建Mock对象,并使用Mockito.when、Mockito.verify等方法来模拟对象的行为和验证方法调用。

但是,如果我们不调用MockitoAnnotations.initMocks(this)方法,这些Mock对象就无法被正确初始化,从而导致测试失败。因此,我们通常在@Before注解方法中调用这个方法,以确保所有的Mock对象都已经被正确初始化。

在具体实现中,MockitoAnnotations.initMocks(this)方法会扫描测试类中所有的@Mock、@Spy、@InjectMocks注解,并根据注解中的类型和名称来创建对应的Mock对象,并将这些对象注入到测试类中。这样,在测试过程中就可以使用这些Mock对象来模拟外部依赖,从而实现单元测试的独立性和可重复性。

Mockito.when(userDao.getUserById(1L)).thenReturn(mockUser);

Mockito.when(userDao.getUserById(1L)).thenReturn(mockUser)这行代码的作用是使用Mockito框架来模拟userDao.getUserById方法的行为。

具体来说,Mockito.when方法会返回一个Mockito的OngoingStubbing对象,用于进一步指定模拟方法的返回值或抛出异常。在这个例子中,我们使用thenReturn方法来指定当userDao.getUserById(1L)方法被调用时,返回一个预先构造好的mockUser对象。

当测试中调用userService.getUserById(1L)方法时,Mockito框架会捕获这个方法调用,并返回预先定义的mockUser对象,从而避免对外部环境的依赖,保证单元测试的独立性。

这里还要补充一点,Mockito.when方法并不是真正的模拟方法调用,它只是记录了一个Stubbing规则,告诉Mockito在测试运行过程中如何处理这个方法调用。只有当真正调用模拟的方法时,Mockito才会根据Stubbing规则返回预先定义的值或抛出异常。

在具体实现中,Mockito.when方法会根据指定的方法调用和参数,生成一个MethodInvocation对象,用于表示这个方法调用的信息。然后,Mockito会将这个MethodInvocation对象和Stubbing规则保存到一个全局的InvocationContainer中,用于在测试过程中捕获和处理对这个方法的调用。

Mockito 怎么知道我的 UserService 调用到了我的 UserDao 方法了呢?

Mockito能够知道UserService是否调用了UserDao方法,是通过代理对象来实现的。

在这个示例中,我们使用了Spring的依赖注入(DI)框架来注入UserService和UserDao对象,使得UserService依赖于UserDao对象。在测试中,我们使用Mockito来创建一个Mock的UserDao对象,并将这个对象注入到UserService中。由于UserService中的UserDao对象被Mockito替换成了Mock对象,我们就能够捕获UserService对UserDao方法的调用。

具体来说,当我们调用UserService中的getUserById方法时,实际上是调用了Mockito所创建的一个代理对象的getUserById方法。这个代理对象能够捕获所有的方法调用信息,并将这些信息保存到Mockito的InvocationContainer中。然后,Mockito根据这些调用信息来判断是否需要进行Stubbing,即模拟方法调用的返回值或抛出异常。

当我们使用Mockito.when方法来定义UserDao的getUserById方法的返回值时,Mockito就会根据InvocationContainer中的调用信息来确定是否应用这个Stubbing规则。如果当前的调用信息和Mockito.when方法定义的规则匹配,Mockito就会返回预定义的值或抛出预定义的异常。

因此,Mockito能够知道UserService是否调用了UserDao方法,是通过代理对象捕获所有的方法调用信息,并根据这些信息来判断是否需要进行Stubbing来实现的。

Mockito 调用模拟对象全解析

  1. 使用Java反射机制创建一个代理对象,代理对象的类型是Mock对象的接口或类。
  2. 代理对象能够记录Mock对象的所有方法调用信息,并将这些信息保存到一个全局的InvocationContainer对象中。
  3. 在使用Mockito.when方法定义Mock对象的方法行为时,Mockito会将这些Stubbing规则保存到InvocationContainer对象中,以便在测试过程中捕获和处理方法调用。
  4. 在测试过程中,当我们调用Mock对象的方法时,代理对象会捕获这个方法调用信息,Mockito会根据InvocationContainer中保存的所有Invocation对象来匹配相应的Stubbing规则,并返回预定义的值或抛出预定义的异常。
  5. 在测试结束时,我们可以使用Mockito.verify方法来验证Mock对象的方法调用是否符合预期,从而实现单元测试的有效性和可靠性。

因此,Mockito能够调用到我们通过when注册到InvocationContainer的调用信息,是通过代理对象捕获方法调用信息,并将它们保存到InvocationContainer中实现的。在测试过程中,我们可以使用Mockito提供的各种方法来定义Mock对象的行为和验证方法调用,从而实现单元测试的独立性和可重复性。文章来源地址https://www.toymoban.com/news/detail-731065.html

到了这里,关于Mockito 调用模拟对象全解析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android单元测试系列(3)-Mock之Mockito

    目录 一、官网 二、Demo示例 1. 目录结构 2. 被测试的类 3. 测试类 三、Mockito方法说明 1. mock对象创建 2. Mockito框架中的常见方法说明 2.1 常见的打桩方法 2.2 常见的验证行为 2.3 其他方法  3. Mockito的局限性 Mockito: https://github.com/mockito/mockito Mockito (Mockito 4.4.0 API) 为什么要用mock:

    2023年04月15日
    浏览(36)
  • JUnit 5单元测试(三)—— Mockito 模拟

    上一篇讲了 JUnit 5单元测试(二)—— 断言,书接上文开始 JUnit 5单元测试(三)—— Mockito 模拟 想象下面这几种情况你该怎么单元测试: 1.A方法去数据库查询了数据进行了一些处理,该怎么单元测试; 2.在微服务项目中,A方法中调用了远程微服务B方法(或者B方法还没写好

    2024年02月15日
    浏览(51)
  • SpringBoot单元测试java.lang.IllegalStateException Could not initialize plugin: interface org.mockito解决方案

      大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作

    2024年02月04日
    浏览(44)
  • 单元测试 Mock 对象为null

    场景:单元测试mock对象,执行时为null或值不符。 单元测试中mock方法并doReturn了mock数据,但是实际的方法在后面使用的参数却是null。 断点调试后发现调用方法前和在方法中的对象的id并非一个; 重复浏览调用代码,发现问题在于单测中重复mock一个方法,doReturn的mock数据被覆

    2024年02月11日
    浏览(33)
  • 【SpringBoot】mockito+junit 单元测试

    CommonServiceImpl 在方法 getSourceCodeMap() 调用了 ServiceA 的方法 list(QueryBO queryBo) 。 org.mockito.exceptions.base.MockitoException: No tests found in ClientSyncServiceImplTest Is the method annotated with @Test? Is the method public? 解决方案: Test引入 org.junit.Test 不要引入 org.junit.jupiter.api.Test 例如获取当前用户 moc

    2024年02月09日
    浏览(44)
  • C++类对象单元测试中的Mock使用

      在进行单元测试时,我们想要测试自己缩写 函数A ,但是 函数A 却依赖于 函数B ,当 函数B 无法满足预期时就无法对 函数A 进行测试,主要由于下面几个原因: 函数B 依赖于硬件设备 真实的 函数B 的返回值无法满足我们的预期 团队开发中 函数B 尚未实现   这时就需要

    2023年04月15日
    浏览(41)
  • Mock单元测试----对于流程中的异常模拟,实现覆盖

    前言:进行单元测试时,有时候无法编写合适的测试用例来满足流程中的异常捕获和catch内的后续操作,此时mock模拟就有大作用了 例如:在进行删除操作时,为了防止在删除过程中突发数据库断连等情况,使用了try、catch进行异常的捕获和输出,但是在单元测试中编写测试实

    2024年02月12日
    浏览(38)
  • mockito+junit 单元测试 测试私有方法利用反射去调用提升覆盖率 反射调用时传入参数为 null

    今天公司安排我写单元测试 因为要通过三级认证 公司要求是覆盖率必须达到100% 而在写单元测试的时候 对于是否要测试私有方法一直是一个争议 公司规范 对私有方法也进行测试 代码如下: JudgeUtils 是公司封装的一个工具类 让我们看看 isNull 方法的内部 代码如下: 我现在需

    2024年02月11日
    浏览(48)
  • SpringBoot单元测试--Mockito+Junit5框架使用

    作为程序员为了提前发现代码bug,优化代码; 通常我们写完某个功能模块代码后都需要写单元测试对代码块进行测试(特别是敏捷开发中);Java项目最常用的单元测试框架即为Junit(目前最新版本为Junit5),SpringBoot本身也整合了该框架。在写单元测试时代码块中的调到第三方接口方

    2024年02月02日
    浏览(46)
  • SpringBoot 使用Mock单元测试

    测试一般分为两种黑盒测试和白盒测试。         黑盒测试又称为 功能测试 或 数据驱动测试 ,测试过程中,程序看作成一个黑色盒子,看不到盒子内部代码结构。         白盒测试又称为 结构测试 或 逻辑驱动测试 ,测试过程中,程序看作一个透明盒子,能够看清

    2024年03月20日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包