当前位置:   article > 正文

Mockito单元测试_mock单元测试

mock单元测试

1.使用Mockito创建单元测试的三种方式


1.springboot 项目需要引入以下依赖,spring-boot-starter-test 集成Mockito 不需要额外单独引入

  1. <dependency>
  2.          <groupId>org.springframework.boot</groupId>
  3.          <artifactId>spring-boot-starter-test</artifactId>
  4.          <scope>test</scope>
  5.      </dependency>
  6.    <!--  不需要额外单独引入  不是Springboot项目需要引入以下依赖>
  7.       <dependency>
  8.             <groupId>org.mockito</groupId>
  9.             <artifactId>mockito-core</artifactId>
  10.             <version>4.0.0</version>
  11.             <scope>compile</scope>
  12.     </dependency>
  13.     <dependency>
  14.             <groupId>org.mockito</groupId>
  15.             <artifactId>mockito-junit-jupiter</artifactId>
  16.             <version>4.0.0</version>
  17.             <scope>compile</scope>
  18.     </dependency>


2.使用junit5 创建单元测试的第一种方式,在创建的测试类种添加@ExtendWith(MockitoExtension.class) 注解,如果你使用的是junit4 请使用@RunWith(MockitoJunitRunner.class)

  1. /**
  2.  * 使用junit5 创建Mockito 单元测试的第一种方式
  3.  */
  4. @ExtendWith(MockitoExtension.class)
  5. class SecurityApplicationTests {
  6.     
  7.     @Mock
  8.     private UserServiceImpl userService;
  9. }


3.使用junit5 创建单元测试的第二种方式,使用Mockito.mock静态方法创建Mock对象

  1. class SecurityApplicationTests {
  2.     private UserServiceImpl userService;
  3.     @BeforeEach
  4.     public void init() {
  5.         userService = Mockito.mock(UserServiceImpl.class);
  6.     }
  7. }


4.使用junit5 创建单元测试的第三种方式,使用MockitoAnnotations.openMocks加@Mock 注解的方式创建

  1. class SecurityApplicationTests {
  2.     @Mock
  3.     private UserServiceImpl userService;
  4.     @BeforeEach
  5.     public void init() {
  6.         MockitoAnnotations.openMocks(this);
  7.     }
  8. }

2.Mock对象和Spy 对象的区别(Spy 也是一个特殊的Mock对象)

Mock对象方法插桩方法不插桩作用对象最佳实践
Mock对象执行插桩逻辑返回Mock的默认值类,接口被测试类或其依赖
Spy 对象执行插桩逻辑调用真实的方法类,接口被测试类

1.方法插桩的两种方式

1.创建一个Mock对象 mockList,给List 集合的index 为0 下标位置插桩,然后使用断言去判断

需要注意的是:doReturn("World").when(mockList).get(0) 方法执行的对象可以是mock或者spy对象,而when(mockList.get(0)).thenReturn("Hello") 只能执行mock对象

        

  1. @ExtendWith(MockitoExtension.class)
  2. class SecurityApplicationTests {
  3. @Mock
  4. private List<String> mockList;
  5. @Test
  6. public void test1() {
  7. //插桩
  8. doReturn("World").when(mockList).get(0);
  9. when(mockList.get(0)).thenReturn("Hello");
  10. // 使用断言验证
  11. Assertions.assertEquals("Hello", mockList.get(0));
  12. }
  13. }

2.返回值为void 时使用的插桩方式

  1. @ExtendWith(MockitoExtension.class)
  2. class SecurityApplicationTests {
  3. @Mock
  4. private List<String> mockList;
  5. @Test
  6. public void test1() {
  7. // 返回值是void时使用的插桩方式
  8. doNothing().when(mockList).clear();
  9. mockList.clear();
  10. // 由于没有返回值,无法用断言判断,可以使用verify的方式去看执行的次数
  11. verify(mockList, times(1)).clear();
  12. }
  13. }

3.插桩抛出异常

  1. @ExtendWith(MockitoExtension.class)
  2. class SecurityApplicationTests {
  3. @Mock
  4. private List<String> mockList;
  5. @Test
  6. public void test4() {
  7. // 插桩mockList 执行get方法时抛出异常
  8. doThrow(new RuntimeException()).when(mockList).get(anyInt());
  9. try {
  10. mockList.get(4);
  11. //如果没有抛出异常,则测试失败
  12. Assertions.fail("Should have thrown an exception");
  13. }catch (Exception e){
  14. Assertions.assertTrue(e instanceof RuntimeException);
  15. }
  16. }
  17. }

4.多次插桩

  1. @ExtendWith(MockitoExtension.class)
  2. class SecurityApplicationTests {
  3. @Mock
  4. private List<String> mockList;
  5. @Test
  6. public void test4() {
  7. //第一次调用返回hello, 第二次返回world, 第三次即以后都返回java
  8. when(mockList.get(0)).thenReturn("hello")
  9. .thenReturn("world")
  10. .thenReturn("java");
  11. Assertions.assertEquals("hello", mockList.get(0));
  12. Assertions.assertEquals("world", mockList.get(0));
  13. Assertions.assertEquals("java", mockList.get(0));
  14. }
  15. }

@InjectMocks 注解的使用

作用:若@InjectMocks 声明的变量需要用到mock/spy的对象mockito会自动使用当前类里的mock或spy对象进行按类型或名字的注入

注意事项:被@InjectMocks注解标注的属性必须是实现类,因为mockito会创建对应的实例对象,默认创建的对象未经过mockito的处理,因此配合@spy 注解使其变为mock 对象调用真实的方法

SpringBoot 实战

1.有如下代码,

  1. @Service
  2. public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService{
  3. @Resource
  4. private UserMapper userMapper;
  5. @Cacheable(value = "user", key = "#root.method.name + #username")
  6. public User getUserByUserName(String username) {
  7. QueryWrapper queryWrapper = new QueryWrapper();
  8. queryWrapper.eq("user_name", username);
  9. return userMapper.selectOne(queryWrapper);
  10. }
  11. }

2.选择类名,按Alt + Enter 键创建测试类,勾选Member 创建以图中命名的测试方法

3. 编写测试逻辑

  1. @ExtendWith(MockitoExtension.class)
  2. class UserServiceImplTest {
  3. @Spy
  4. @InjectMocks
  5. UserServiceImpl userService;
  6. @Mock
  7. UserMapper userMapper;
  8. @Test
  9. void getBaseMapper() {
  10. String username = "testuser";
  11. User expectedUser = new User();
  12. expectedUser.setId(1L);
  13. expectedUser.setUserName(username);
  14. when(userMapper.selectOne(any(QueryWrapper.class))).thenReturn(expectedUser);
  15. User actualUser = userService.getUserByUserName(username);
  16. assertEquals(expectedUser, actualUser);
  17. }
  18. }

4.运行测试类,下图种显示代码测试覆盖率

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/煮酒与君饮/article/detail/895875
推荐阅读
  

闽ICP备14008679号