Mockito @Spy 在相同类型的字段上

Mockito @Spy on fields of the same type

我有以下单元测试,其中有以下模拟和间谍。

@Spy
private Map<String, String> rulesObjects = new HashMap<>();

@Spy
private Map<String, Map<String, List<String>>> mandatoryFieldObject = new HashMap<>();

@Mock
private configProperties configProperties;

@InjectMocks
private LoaderService loaderService;

@Test
@DisplayName("This test should load the config files in memory")
void initRuleMaps() throws IOException {
    this.loaderService.initRuleMaps();
    assertThat(this.rulesObjects)
            .isNotEmpty()
            .hasSize(3);
}

initRuleMaps 的逻辑调用这 2 个方法;

private void saveRulesInCache() throws IOException {
    rulesObjects.put(EmvcoConstants.LEGACY, dataLegacy);
    rulesObjects.put(EmvcoConstants.LEGACY1, dataLegacy1);
    rulesObjects.put(EmvcoConstants.LEGACY2, dataLegacy2);
}

private void saveMandatoryFieldListInCache() throws IOException {
    for (Map.Entry<String, String> type: this.configProperties.getTypes().entrySet()) {
        Map<String, List<String>> mandatoryRuleFiledMap = getMandatoryRuleFiled(qrType.getKey());
        mandatoryFieldObject.put(type.getValue(), mandatoryRuleFiledMap);
    }

}

在方法initRuleMaps中,对两个地图都有一些计算。每个应该有 3 个条目。但是正在发生的事情似乎只创建了一个间谍,并且所有计算都只在一个对象上完成。因此我得到 6 个条目。

看每个间谍的引用,其实都是一样的

有什么解决办法吗?

谢谢。

我猜你的问题出在 @InjectMocks 上,它无法区分两个地图:https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/InjectMocks.html

Field injection; mocks will first be resolved by type (if a single type match injection will happen regardless of the name), then, if there is several property of the same type, by the match of the field name and the mock name.

Note 1: If you have fields with the same type (or same erasure), it's better to name all @Mock annotated fields with the matching fields, otherwise Mockito might get confused and injection won't happen.

Note 2: If @InjectMocks instance wasn't initialized before and have a no-arg constructor, then it will be initialized with this constructor.

我认为你的问题在于擦除(这两个字段确实具有相同的类型:Map)。

您应该尝试将 Mock/Spy 命名为:@Mock(name = "database"),名称与 @InjectMocks.

中的字段相同

或者,创建一个构造函数并自己完成:new LoaderService(rulesObjects, mandatoryFieldObject, configProperties)