mock

发布时间 2023-12-13 10:59:35作者: zhegeMaw

1、mock使用流程

  • 0、初始化:必须使用@RunWith(MockitoJUnitRunner.class)或Mockito.initMocks(this)初始化这些模拟并注入它们。

  • 1、创建mock对象:对于不容易构造的类, 使用注解@Mock构建虚拟对象

  • 2、测试方法实现

    • 构造参数

    • 打桩:当执行该类中的某些方法时 指定输入输出

    • 调用需要测试的方法

    • 验证结果

参考:https://blog.csdn.net/moshowgame/article/details/100983711

 

2、@Mock、@Spy和@InjectMock的区别

  • Mock:创建一个虚拟对象。可以用来模拟方法的返回值,以便在测试中对其进行测试。

  • InjectMock:执行真实的方法,可以注入mock对象。(打桩推荐when……then)

  • spy:灵活控制真实执行/跳过方法。spy 对象是真实对象的代理,当你不对它进行设置的时候,所有的调用都会转发给真实的对象。如果你对 spy 对象进行了设置,那么这个设置将会覆盖真实对象的行为。

    • 使用Spy包装真实对象时使用when(….).thenReturn(….)将无效,必须使用 doReturn(…).when(…)来进行插桩

  • 两种打桩区别:

    • when(...) thenReturn(...)会调用真实的方法,并返回指定结果。如果你不想调用真实的方法而是想要mock的话,就不要使用这个方法。

    • doReturn(...) when(...) 不会调用真实方法

总的来说,`mock`用于创建本地伪造对象的对象, 而`injectmock`用于将伪造或模拟的对象添加到你的代码中。当我们在写单元测试时,我们可以使用Mock来代替需要复杂的对象或服务,以便我们可以集中精力测试特定的代码片段。而使用InjectMocks时, 开发人员可以将Mock对象注入到需要被测试的类中,并且可以测试类和Mock之间的交互和协作。

 

3、使用示例

  • Spy + Mock + InjectMock :执行真实的方法,同时又需要打桩,需要注入mock对象。

@RunWith(MockitoJUnitRunner.class)
public class ParamPaddingComponentTest {

  //spy注解: 该实例执行真实的方法,且可以打桩
  //InjectMocks注解: 可以将其他mock对象注入到ParamPaddingComponent
    @Spy
    @InjectMocks
    private ParamPaddingComponent paramPaddingComponent;

  //将依赖mock为虚拟对象
    @Mock
    private MetaInfoHolder metaInfoHolder;

    @Before
    public void init() {
    }
    
    @Test
       public void testProcessNoParams() throws Exception {
        // 构造参数
        ExecutionContext executionContext = new ExecutionContext();
        executionContext.setApiUri("v1/test");
        executionContext.setAppId("123456789");
        Optional<Map> defaultValuesCfg = Optional.of(JsonUtils.fromJson("{\"audioFormat\":\"pcm\", \"sampleRate\":16000}", Map.class));
        // 打桩
        Mockito.doReturn(executionContext).when(paramPaddingComponent).getContextBean(Mockito.any());
        Mockito.doReturn(defaultValuesCfg).when(metaInfoHolder).getFixedConfg(LionGroupEnum.API_DEFAULTVALUES_CFG.getGroupName(), "v1/test-123456789");
       //调用方法
        paramPaddingComponent.process();
       //验证结果
        Map<String, Object> expectResult = new ConcurrentHashMap<>();
        expectResult.put("sampleRate", 16000);
        expectResult.put("audioFormat", "pcm");
        Assert.assertEquals(expectResult, executionContext.getRequestParams());
    }
}

4、使用限制

  • 不能 mock 静态方法

  • 不能 mock private 方法

  • 不能 mock final class