java单元测试:Mockito常用技巧

Mockito是Java中最流行的Mock框架之一,主要用于创建和配置模拟对象(Mock),以测试代码的行为。Mockito使得单元测试更加简单和可控,特别是在需要隔离外部依赖的情况下。

  1. Mockito简介

  1.1 什么是Mockito

  Mockito是一个开源的Mock框架,旨在为Java单元测试提供简单、可读的Mock对象。它可以模拟类的行为,使测试代码能够在不依赖真实对象的情况下运行。

  1.2 为什么使用Mockito

  ·隔离外部依赖:可以模拟外部系统(如数据库、网络服务等),使测试更加独立。

  · 提高测试覆盖率:即使没有实现具体逻辑,也可以编写测试,确保接口和交互逻辑正确。

  · 便于测试边界条件:可以轻松模拟异常情况和边界条件,确保代码在各种情况下的稳定性。

  2. 安装Mockito

  使用Maven来安装Mockito依赖,编辑pom.xml文件,添加Mockito依赖:

 <dependency>
      <groupId>org.mockito</groupId>
      <artifactId>mockito-core</artifactId>
      <version>4.0.0</version>
      <scope>test</scope>
  </dependency>

如果你使用JUnit 5,还需要添加Mockito的JUnit 5扩展:

<dependency>
      <groupId>org.mockito</groupId>
      <artifactId>mockito-junit-jupiter</artifactId>
      <version>4.0.0</version>
      <scope>test</scope>
  </dependency>

3. Mockito的核心功能

  3.1 创建Mock对象

  使用Mockito.mock()方法可以创建一个Mock对象:

import static org.mockito.Mockito.*;
  import org.junit.jupiter.api.Test;
  import static org.junit.jupiter.api.Assertions.*;
  public class UserServiceTest {
      @Test
      void testAddUser() {
          UserRepository mockRepository = mock(UserRepository.class);
          UserService userService = new UserService(mockRepository);
          User user = new User("John", "Doe");
          when(mockRepository.save(user)).thenReturn(user);
          User result = userService.addUser(user);
          assertEquals("John", result.getFirstName());
          verify(mockRepository, times(1)).save(user);
      }
  }

 3.2 配置Mock对象行为

  使用when和thenReturn方法配置Mock对象的行为:

UserRepository mockRepository = mock(UserRepository.class);
  User user = new User("John", "Doe");
  when(mockRepository.save(user)).thenReturn(user);

你还可以配置方法抛出异常:

when(mockRepository.save(user)).thenThrow(new RuntimeException("Save failed"));

 3.3 验证方法调用

  使用verify方法验证Mock对象的方法是否被调用,以及调用次数:

verify(mockRepository, times(1)).save(user);

常见的验证方法包括:

  ·verify(mock).methodCall():验证方法被调用

  · verify(mock, times(n)).methodCall():验证方法被调用n次

  · verify(mock, never()).methodCall():验证方法从未被调用

  3.4 参数匹配

  Mockito提供了多种参数匹配器(Matchers)用于更灵活的验证和配置行为:

import static org.mockito.ArgumentMatchers.*;
  when(mockRepository.findById(anyInt())).thenReturn(Optional.of(user));
  verify(mockRepository).findById(eq(1));

常见的匹配器包括:

  ·any():匹配任何参数

  · anyInt():匹配任何整数参数

  · eq(value):匹配特定值

  · isNull():匹配null值

  · notNull():匹配非null值

  4. 使用注解简化Mock配置

  Mockito提供了注解(Annotations)来简化Mock对象的创建和配置:

  4.1 @Mock

  @Mock注解用于创建Mock对象:

import org.junit.jupiter.api.BeforeEach;
  import org.junit.jupiter.api.Test;
  import org.mockito.InjectMocks;
  import org.mockito.Mock;
  import org.mockito.MockitoAnnotations;
  import static org.mockito.Mockito.*;
  public class UserServiceTest {
      @Mock
      private UserRepository userRepository;
      @InjectMocks
      private UserService userService;
      @BeforeEach
      void setUp() {
          MockitoAnnotations.openMocks(this);
      }
      @Test
      void testAddUser() {
          User user = new User("John", "Doe");
          when(userRepository.save(user)).thenReturn(user);
          User result = userService.addUser(user);
          assertEquals("John", result.getFirstName());
          verify(userRepository, times(1)).save(user);
      }
  }

4.2 @InjectMocks

  @InjectMocks注解用于自动注入Mock对象到被测试对象中:

 @InjectMocks
  private UserService userService;

5. 高级功能

  5.1 Spy

  Spy用于部分模拟对象,即部分使用真实对象的方法,部分使用Mock对象的方法:

List<String> list = new ArrayList<>();
  List<String> spyList = spy(list);
  when(spyList.size()).thenReturn(100);
  spyList.add("one");
  spyList.add("two");
  assertEquals(100, spyList.size());
  assertEquals("one", spyList.get(0));
  assertEquals("two", spyList.get(1));

5.2 ArgumentCaptor

  ArgumentCaptor用于捕获方法调用时传递的参数:

 import org.mockito.ArgumentCaptor;
  ArgumentCaptor<User> captor = ArgumentCaptor.forClass(User.class);
  verify(userRepository).save(captor.capture());
  User capturedUser = captor.getValue();
  assertEquals("John", capturedUser.getFirstName());

6. 实践中的Mockito

  6.1 模拟依赖

  在实际项目中,Mockito常用于模拟依赖对象,如数据库访问层、远程服务等,使测试更加独立和可控。

  6.2 与JUnit结合

  Mockito通常与JUnit结合使用,特别是JUnit 5,利用@ExtendWith(MockitoExtension.class)简化Mock对象的初始化。

import org.junit.jupiter.api.extension.ExtendWith;
  import org.mockito.junit.jupiter.MockitoExtension;
  @ExtendWith(MockitoExtension.class)
  public class UserServiceTest {
      // 测试代码
  }

7. 总结

  Mockito是一个强大的Mock框架,为Java开发者提供了丰富的功能来创建和配置Mock对象。通过使用Mockito,可以隔离外部依赖,提高测试的独立性和稳定性。掌握Mockito的核心功能和高级用法,可以帮助你编写高效、可靠的单元测试。

感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:

 

这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!有需要的小伙伴可以点击下方小卡片领取   

  • 21
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值