Mockito测试环境搭建 | 整合Springboot | 常用注解详解

在这里插入图片描述

仅使用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 {

    // 通过Spring容器管理的UserService实例
    @Autowired
    private UserService userService;

    // 部分模拟UserDao对象,替换Spring容器中的UserDao bean
    @SpyBean
    private UserDao userDao;

    // 模拟WebServiceClient对象,替换Spring容器中的WebServiceClient bean
    @MockBean
    private WebServiceClient webServiceClient;
    //被替换的两个Mock对象可以被Spring容器自动注入到userService中
    
    //省略测试方法
}

注意:

当你使用 @MockBean@SpyBean注解时,不需要 调用 MockitoAnnotations.openMocks(this);,因为 @MockBean 是由 Spring Boot 管理的,Spring Boot 会自动初始化并处理 @MockBean 创建的模拟对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值