mock静态方法指引

mock静态方法指引

mockito 在3.4.0版本开始支持mock static method

文档:https://wttech.blog/blog/2020/mocking-static-methods-made-possible-in-mockito-3.4.0/

1. 升级Maven依赖

<!-- mockito -->
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>3.6.28</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-inline</artifactId>
    <version>3.6.28</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-junit-jupiter</artifactId>
    <version>3.4.0</version>
    <scope>test</scope>
</dependency>

2. 使用方式

  • 静态方法
public final class MysteryBox {

    public static Optional<Mystery> amaze(String codeWord) {
        // todo
    }
}
  • 待测试的类,使用了MysteryBox.amaze(String)静态方法
public class HaplessUser {

  public Mystery unleashMystery(String magicSpell) {
    Optional<Mystery> om = MysteryBox.amaze(magicSpell);
    return om.orElseThrow(() -> new FailureToAmazeException("The box was empty"));
  }
}
  • 单元测试类,mock静态方法
@Test
@DisplayName("Should throw an exception upon failing to uncover mind-boggling mysteries")
void testUncoverMysteries() {

  // 1.在try代码块中实例化一个MockedStatic,使用范围仅仅在try代码块内
  try (MockedStatic<MysteryBox> mb = Mockito.mockStatic(MysteryBox.class)) {

    // 2. mock静态方法的调用
    mb.when(() -> { MysteryBox.amaze(any(String.class )) })
      .thenReturn(Optional.empty());
    
    // 3. 调用单元测试方法
    assertThrows(FailureToAmazeException.class, () -> subjectUnderTest.unleashMystery("Abracadabra"));

  }
  // 静态方法的mock在这里是不可用的
}

3. 异常情况

在同个测试类,当多个测试方法都需要mock调用某个静态方法时,代码如下

@ExtendWith(MockitoExtension.class)
public class KonfigurationCopyServiceTest {

  @InjectMocks
	private EKonfigurationCopyServiceImpl konfigurationCopyServiceImpl;
	
	@MockBean
	private FileProcessRecordServiceImpl fileProcessRecordService;

  @BeforeEach
  public void setUp() {
    // mock静态方法
		MockedStatic<SpringUtil> mockSpringUtil = Mockito.mockStatic(SpringUtil.class);
		mockSpringUtil.when(() -> SpringUtil.getActiveProfile()).thenReturn("dev");
    
  }
  @Test
  void test1() {
 	  // 省略@Test的单元测试方法 
  }
  @Test
  void test2() {
 	  // 省略@Test的单元测试方法 
  }
}

此时,会抛出如下异常信息:

org.mockito.exceptions.base.MockitoException: 
For xx.xxxx.util.SpringUtil, static mocking is already registered in the current thread

To create a new mock, the existing static mock registration must be deregistered

静态mock已经在当前线程中注册了,要创建新的mock,必须注销现有的静态mock注册

解决方式
  • 导入
import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS;
  • 在测试类上添加注解@TestInstance(PER_CLASS)
  • 使用@BeforeAll代替@BeforeEach
// 添加@TestInstance(PER_CLASS)注解
@TestInstance(PER_CLASS)
@ExtendWith(MockitoExtension.class)
public class KonfigurationCopyServiceTest {

  @InjectMocks
	private EKonfigurationCopyServiceImpl konfigurationCopyServiceImpl;
	
	@MockBean
	private FileProcessRecordServiceImpl fileProcessRecordService;

  // 使用@BeforeAll mock静态方法
  @BeforeAll
  public void setUp() {
    // mock静态方法
		MockedStatic<SpringUtil> mockSpringUtil = Mockito.mockStatic(SpringUtil.class);
		mockSpringUtil.when(() -> SpringUtil.getActiveProfile()).thenReturn("dev");
    
  }
  
  @BeforeEach
  public void init() {
    // mock其他方法
    
  }
  @Test
  void test1() {
 	  // 省略@Test的单元测试方法 
  }
  @Test
  void test2() {
 	  // 省略@Test的单元测试方法 
  }
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值