SpringBoot整合Mockito进行单元测试超全详细教程 JUnit断言 Mockito 单元测试

在这里插入图片描述

Mock概念

Mock叫做模拟对象,即用来模拟未被实现的对象可以预先定义这个对象在特定调用时的行为(例如返回值或抛出异常),从而模拟不同的系统状态。

导入Mock依赖

pom文件中引入springboot测试依赖,spring-boot-starter-test中包含了Mockito

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

Mock测试环境和Spring上下文环境

仅使用Mock环境

使用Mock进行测试时候,可以仅仅使用Mock环境,不添加@SpringBootTest,这个时候不会加载Spring上下文(@Autowired等不会起作用),需要手动处理使用@Mock和@InjectMock来处理类之间的依赖关系。

常用注解:
@Mock:

@Mock 是 Mockito 提供的注解,用于生成模拟对象,是创建了一个新的对象。这里的 userDaowebServiceClient 是通过 Mockito 模拟的对象,而不是 Spring 容器中的实际 bean。它们的行为可以通过 when/thenReturn 或其他模拟方法来定义。

注意:当你使用 Mockito@Mock 注解来 mock 一个类时,即使该类已经实现了部分方法,Mockito 也会拦截这些方法的调用。这意味着,默认情况下,Mockito 会模拟这个类的所有方法(包括已经实现的方法),除非你显式定义模拟行为。

因此,当你通过 @Mock 来 mock 一个已经实现部分方法的类时:

  • 如果你调用了已经实现的方法,并且没有为这个方法定义具体的 when/thenReturn 行为,Mockito 会返回 默认值(例如 null、0、false 等),而不会执行类中的实际实现。
  • 如果你想让某些方法在调用时执行它们的实际实现,你需要使用 Mockito 提供的 spy() 功能。
@Spy

@Spy 创建的对象是真实对象的部分模拟(Partial Mock),它会调用对象的真实方法,而只有那些明确模拟的方法才会被替换成模拟的行为。spy() 提供部分模拟功能。未被显式模拟的方法将调用实际实现,已经被模拟的方法则返回预设的模拟值。

在使用 @InjectMocks 时,Mockito 会将 @Mock@Spy 注解的对象注入到被测试的对象中。如果某个依赖项使用了 @Spy,Mockito 会确保被注入的是该对象的部分模拟实现。

spy()mock() 的对比

特性

mock()

spy()

默认行为

模拟所有方法,返回默认值(如 null

调用真实的实现,除非被显式模拟

是否执行实际代码

不执行

执行实际的代码实现

定义模拟行为时是否拦截

会拦截并返回模拟值

如果定义了模拟行为,使用模拟值,没定义则执行实际实现

@InjectMocks:
  • @InjectMocks 是 Mockito 的一个注解,用于将模拟对象(即用 @Mock 创建的对象)注入到被测对象中(这里是 UserService)。
  • Mockito 会创建一个新的 UserService 对象,并将 userDaowebServiceClient 作为依赖注入到这个新的对象中。
  • 与 Spring 容器的行为无关。即使 UserService 已经通过 @Service 注解注册到了 Spring 容器中,在使用 @InjectMocks 时,Mockito 会创建并管理一个全新的 UserService 对象
具体演示:
//UserDao定义
public class UserDao {
    //getUserById有真实的实现
    User getUserById(int userId)
    {
        return new User(1,"张三");
    }
    int saveUser(User user);
}


//WebServiceClient定义
public class WebServiceClient {
    boolean isServiceAvailable();
    String getUserDataFromWebService(int userId);
}


@Service
//UserService依赖于UserDao以及WebServiceClient
public class UserService {
	
    @Autowired
    private UserDao userDao;

    @Autowired
    private WebServiceClient webServiceClient;
    
    //省略操作
}


//可以没有@SpringBootTest
public class UserServiceTest {

    // 使用@Spy部分模拟UserDao对象
    @Spy
    private UserDao userDao;

    // 模拟WebServiceClient对象
    @Mock
    private WebServiceClient webServiceClient;

    // 根据依赖将mock对象注入到UserService中
    @InjectMocks
    private UserService userService;
    
    //必须首先初始化
    @BeforeEach
    public void setUp() {
        //非常重要!!!!!
        MockitoAnnotations.openMocks(this);  // 初始化Mockito
    }
    
    @Test
    void Spytest()
    {
        //模拟saveUser方法,而调用getUserById为其真实实现
        doReturn(1).when(userDao).saveUser(any(User.class));
        //真实行为
        User FoundUser = userDao.getUserById(1);// User张三
        //模拟行为
        userDao.saveUser(FoundUser);// 返回1
        
	}
    
    //省略其他测试方法
}
MockitoAnnotations.openMocks(this)作用:

MockitoAnnotations.openMocks(this) 是用于初始化 @Mock@Spy@InjectMocks 注解的关键步骤。如果没有这行代码,Mockito 将不会创建和初始化这些模拟对象,导致测试失败。

MockitoAnnotations.openMocks(this) 适用于非 Spring 环境下的单元测试。在 Spring Boot 测试中,你通常使用 @MockBean@Autowired,Spring Boot 会自动处理模拟对象的初始化,因此不需要调用这个方法。

搭配Spring上下文

使用Spring上下文需要使用@MockBean来在测试中将 Spring 容器中的某些 bean 替换为 Mockito 模拟的对象,然后可以使用@Autowired处理类之间的依赖关系。

结合 Spring Boot 和 Mockito 的测试方法
  1. 使用 @MockBean:用来替换 Spring 容器中的 bean,模拟它的行为。
  2. 使用 @Autowired:注入 Spring 容器中实际的服务(如 UserService)。
  3. 使用 @SpringBootTest:启动 Spring Boot 的测试上下文。
常用注解:
@MockBean:

@MockBeanSpring Boot 提供的注解,用于创建一个 Mockito 模拟对象,并将它替换到 Spring 上下文中。userDaowebServiceClient 是通过 @MockBean 模拟的对象,而不是真实的对象。这些模拟对象将替换 Spring 容器中的相应 bean,然后可以通过@Autowird自动注入被依赖类中。

@SpyBean:

@SpyBeanSpring Boot 提供的一个注解,专门用于 部分模拟(Partial Mocking) Spring 容器中的 Bean。它的作用是创建一个部分模拟的对象,部分调用真实方法,部分进行模拟(Mock)行为。相比于 Mockito 提供的 @Spy@SpyBean 更加集成到 Spring 环境中,并且允许你将某个 Spring 容器中的 Bean 替换为部分模拟对象。

@SpyBean 的工作原理

  1. 部分模拟@SpyBean 允许你对 Spring 容器中的现有 Bean 进行部分模拟。这意味着模拟的 Bean 会保留其大部分原始行为,只有你明确模拟的部分会改变。
  2. 注入到 Spring 容器中:使用 @SpyBean 时,Spring Boot 会将该部分模拟的 Bean 注入到 Spring 容器中,替换原有的 Bean。
具体演示:
@Service
public class UserService {

    @Autowired
    private UserDao userDao;

    @Autowired
    private WebServiceClient webServiceClient;
    
    //省略操作
}


@SpringBootTest //使用Spring上下文
public class UserServiceTest {

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值