0

0

Mockito使用中变量值未被覆盖问题的解决

碧海醫心

碧海醫心

发布时间:2025-10-14 09:33:21

|

912人浏览过

|

来源于php中文网

原创

mockito使用中变量值未被覆盖问题的解决

本文旨在解决在使用Mockito进行单元测试时,遇到的变量值无法被Mock覆盖的问题。通过分析问题代码,找出根本原因,并提供清晰的示例代码和解决方案,帮助开发者更好地理解和使用Mockito进行有效的单元测试。本文重点阐述了Mockito的正确使用方式,以及如何避免常见的错误配置,从而确保测试的准确性和可靠性。

在使用Mockito进行单元测试时,经常会遇到需要Mock某些方法的返回值,以便模拟不同的场景。但有时会发现,即使使用了when...thenReturn()或doReturn...when(),目标变量的值仍然没有被覆盖,导致测试结果不符合预期。本文将深入探讨这个问题,并提供解决方案。

理解Mockito的工作原理

Mockito是一个Mocking框架,它允许你创建Mock对象,并定义这些Mock对象的行为。在使用Mockito时,需要理解以下几个关键概念:

  • Mock对象: 是一个模拟的对象,它实现了接口或继承了类,但其行为完全由你控制。
  • Stubbing 是指定义Mock对象的行为,即当调用Mock对象的某个方法时,应该返回什么值或抛出什么异常。
  • Verification: 是指验证Mock对象的某个方法是否被调用,以及被调用了多少次。

常见问题及解决方案

1. 错误的Stubbing对象

最常见的问题是Stubbing了错误的对象。Mockito只能Mock接口和类,而不能Mock对象的属性。在原问题中,尝试直接Mock userEntityTo.getFollowedByEntity() 的返回值是无效的,因为 getFollowedByEntity() 是 userEntityTo 对象的一个方法,而不是一个可以被Mock的对象。

解决方案:

Cursor
Cursor

一个新的IDE,使用AI来帮助您重构、理解、调试和编写代码。

下载

应该Mock userRepository.save(userEntityTo) 方法的返回值,使它返回一个 userEntityTo 对象,该对象的 followedByEntity 属性为 null 或空集合。

2. 代码逻辑问题

另一个常见问题是代码逻辑本身存在问题,导致Mock的返回值没有生效。在原问题中,即使Mock了 userRepository.save(userEntityTo) 的返回值,followUser 方法内部的逻辑仍然会创建 followingRequestEntities 集合,并将其设置到 userEntityTo 对象的 followedByEntity 属性中。因此,userEntityTo.getFollowedByEntity().isEmpty() 永远不会为 true,导致 FollowerNotFoundException 永远不会被抛出。

解决方案:

需要重新审视代码逻辑,确保Mock的返回值能够按照预期影响程序的行为。在本例中,需要修改 followUser 方法的逻辑,或者修改测试用例,使其能够覆盖到 FollowerNotFoundException 被抛出的情况。

3. 正确使用Mockito注解

为了简化Mockito的使用,可以使用Mockito的注解,如 @Mock,@InjectMocks 和 @Spy。

  • @Mock: 用于创建Mock对象。
  • @InjectMocks: 用于将Mock对象注入到被测试的类中。
  • @Spy: 用于创建Spy对象,可以部分Mock真实对象。

示例:

@ExtendWith(MockitoExtension.class)
public class MyTests {
    @Mock
    MyRepository myRepository;

    @InjectMocks
    MyService myService;

    @Test
    public void aTest() {
        when(myRepository.get()).thenReturn("something fake");
        assertEquals("SOMETHING FAKE", myService.doWork());
    }
}

在这个例子中,MyRepository 被Mock,并注入到 MyService 中。在测试方法 aTest 中,定义了当调用 myRepository.get() 方法时,返回 "something fake"。

示例代码

以下是一个完整的示例,展示了如何正确使用Mockito来解决变量值未被覆盖的问题:

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
public class UserServiceTest {

    @Mock
    private UserRepository userRepository;

    @InjectMocks
    private UserServiceImpl userService;

    @Test
    void testFollowUser_ThrowsExceptionWhenFollowerIsNotFound() {
        UUID userFromId = UUID.randomUUID();
        UUID userToId = UUID.randomUUID();
        UserEntity userEntityFrom = new UserEntity();
        userEntityFrom.setId(userFromId);

        UserEntity userEntityTo = new UserEntity();
        userEntityTo.setId(userToId);
        userEntityTo.setName("new name");

        when(userRepository.findById(userEntityFrom.getId())).thenReturn(Optional.of(userEntityFrom));
        when(userRepository.findById(userEntityTo.getId())).thenReturn(Optional.of(userEntityTo));

        // Mock userRepository.save() 方法,返回一个 followedByEntity 为空的 UserEntity 对象
        UserEntity savedUserEntity = new UserEntity();
        savedUserEntity.setId(userToId);
        savedUserEntity.setName("new name");
        savedUserEntity.setFollowedByEntity(new HashSet<>()); // 设置为空集合

        when(userRepository.save(any())).thenReturn(savedUserEntity);

        FollowerNotFoundException exception =
                assertThrows(FollowerNotFoundException.class, () -> userService.followUser(userFromId, userToId));

        assertEquals("Follower Not Found", exception.getMessage());
    }
}

在这个示例中,userRepository.save(any()) 方法被Mock,返回一个 followedByEntity 为空集合的 UserEntity 对象。这样,userService.followUser() 方法中的 if (userEntityTo.getFollowedByEntity() == null || userEntityTo.getFollowedByEntity().isEmpty()) 条件才能成立,从而抛出 FollowerNotFoundException。

注意事项

  • 确保Stubbing的对象是正确的,Mockito只能Mock接口和类。
  • 仔细检查代码逻辑,确保Mock的返回值能够按照预期影响程序的行为。
  • 合理使用Mockito注解,简化测试代码。
  • 避免过度Mock,只Mock必要的依赖,保持测试的简洁性。

总结

在使用Mockito进行单元测试时,遇到变量值未被覆盖的问题,通常是由于错误的Stubbing对象或代码逻辑问题导致的。通过理解Mockito的工作原理,并遵循上述解决方案,可以有效地解决这个问题,编写出高质量的单元测试。记住,Mockito是一个强大的工具,但需要正确的使用才能发挥其作用。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

237

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

458

2024.03.01

if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

780

2023.08.22

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

1155

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

215

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

1965

2025.12.29

java接口相关教程
java接口相关教程

本专题整合了java接口相关内容,阅读专题下面的文章了解更多详细内容。

22

2026.01.19

C++ 设计模式与软件架构
C++ 设计模式与软件架构

本专题深入讲解 C++ 中的常见设计模式与架构优化,包括单例模式、工厂模式、观察者模式、策略模式、命令模式等,结合实际案例展示如何在 C++ 项目中应用这些模式提升代码可维护性与扩展性。通过案例分析,帮助开发者掌握 如何运用设计模式构建高质量的软件架构,提升系统的灵活性与可扩展性。

8

2026.01.30

c++ 字符串格式化
c++ 字符串格式化

本专题整合了c++字符串格式化用法、输出技巧、实践等等内容,阅读专题下面的文章了解更多详细内容。

8

2026.01.30

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 3万人学习

C# 教程
C# 教程

共94课时 | 8万人学习

Java 教程
Java 教程

共578课时 | 53.7万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号