Mockito模拟返回Map异常:填充后Map大小始终为0的问题
问题分析与解决方案
你遇到的核心问题是Mockito的Stubbing时机不对:@InjectMocks会在@Test方法执行前就初始化classUnderTest实例,而你在@Test方法里才对options的方法进行Stub,这时候构造方法已经调用过options.readWhitlist()了,拿到的是Mockito的默认返回值(空Map或者null,根据你的异常信息判断是空Map),所以后续才会触发whiteList.isEmpty()的异常。
下面给你两种可行的解决方案:
方案一:将Stubbing移到@Before方法中
把对options的Stub逻辑提前到测试类初始化阶段,确保classUnderTest实例化时,Stub已经生效。同时要注意,你需要Mock构造方法所需的所有参数(TransportClient和BMECatReader),否则@InjectMocks无法找到合适的构造方法创建实例:
@RunWith(MockitoJUnitRunner.class) public class IndexBMECatTest { @InjectMocks private IndexBMECat classUnderTest; @Mock private CommandLineValues options; @Mock private TransportClient client; // 构造方法依赖的参数必须Mock @Mock private BMECatReader reader; // 构造方法依赖的参数必须Mock @Before public void setUp() { // 提前完成Stub,确保构造方法调用时生效 Map<String, String> testMap = new HashMap<>(); testMap.put("key", "value"); when(options.getCleanFirst()).thenReturn(false); when(options.readWhitlist()).thenReturn(testMap); } @Test public void testAccessoryItemHasNoDublicates() throws Exception { classUnderTest.run(); } }
方案二:手动初始化被测试类
完全控制实例化时机,在所有Stub完成后再创建classUnderTest对象,这样能彻底避免时机问题:
@RunWith(MockitoJUnitRunner.class) public class IndexBMECatTest { private IndexBMECat classUnderTest; @Mock private CommandLineValues options; @Mock private TransportClient client; @Mock private BMECatReader reader; @Test public void testAccessoryItemHasNoDublicates() throws Exception { // 先完成所有Stub逻辑 Map<String, String> testMap = new HashMap<>(); testMap.put("key", "value"); when(options.getCleanFirst()).thenReturn(false); when(options.readWhitlist()).thenReturn(testMap); // 再手动初始化被测试类,确保构造方法拿到Stub后的返回值 classUnderTest = new IndexBMECat(client, options, reader); classUnderTest.run(); } }
补充说明
你之前尝试Mock Map的isEmpty()方法是没必要的,只要能让options.readWhitlist()返回真实的非空Map即可,关键是要保证Stub逻辑在构造方法调用前执行。
内容的提问来源于stack exchange,提问作者davebo92123
相关产品推荐
相关产品推荐

