如何用Mockito Mock方法内新建的MqttWrapper对象(无需PowerMockito)
解决方案
核心思路
利用Mockito 3.5+提供的MockedConstruction拦截所有new MqttWrapper()的调用并生成Mock实例,同时捕获这些实例,用于后续的方法Stub和调用验证。
修改后的测试代码
try(MockedConstruction<MqttWrapper> mockedMqttWrapper = mockConstruction(MqttWrapper.class)){ // 准备依赖Mock mockMethodCalls(); // 获取生产代码中会创建的MqttWrapper Mock实例(仅创建一个,取列表第一个) MqttWrapper mockMqttWrapper = mockedMqttWrapper.constructed().get(0); // Stub getMqttClientConnection方法,匹配捕获到的Mock实例 doReturn(mqttClientConnection).when(mqttClientConnectionManager) .getMqttClientConnection(mockMqttWrapper); // 执行测试方法 mqttWrapperFactoryImpl = spy(new MqttWrapperFactoryImpl(context)); outputMqttWrapper = mqttWrapperFactoryImpl.getMqttWrapperForSiteId(SITE_ID); // 断言返回的实例就是Mock对象 assertEquals(mockMqttWrapper, outputMqttWrapper); // 验证getMqttClientConnection的调用次数和参数 verify(mqttClientConnectionManager, times(1)) .getMqttClientConnection(mockMqttWrapper); verifyNoMoreInteractions(mqttClientConnectionManager); }
关键说明
mockedMqttWrapper.constructed()会返回所有通过new MqttWrapper()创建的Mock实例列表,生产代码仅创建一个,直接取索引0即可。- Stub和验证时必须使用捕获到的Mock实例作为参数匹配条件,确保逻辑严谨性;若无需精确匹配,也可使用
any(MqttWrapper.class)替代。 - 确保Mockito版本在3.5以上,
MockedConstruction是该版本新增特性。
额外优化方案
若createNewMqttWrapperInstance逻辑复杂,可将MqttWrapper的创建逻辑抽为独立protected方法:
protected MqttWrapper createMqttWrapper() { return new MqttWrapper(); }
测试时通过Spy Stub该方法,直接返回预先创建的Mock实例:
MqttWrapper mockMqttWrapper = mock(MqttWrapper.class); mqttWrapperFactoryImpl = spy(new MqttWrapperFactoryImpl(context)); doReturn(mockMqttWrapper).when(mqttWrapperFactoryImpl).createMqttWrapper(); // 后续Stub、执行、验证逻辑与上述一致
内容的提问来源于stack exchange,提问作者piyush bansal
相关产品推荐
相关产品推荐

