Mockito的verify方法被调用,使用了包含特定值的集合。

6

我想确认mocked是否使用特定的字符串作为参数被调用。 例如,我有以下代码:

public class SomeLogic {
    @Autowired
    private SpecificService specificService;

    public void action() {
        Set<String> args = fillArgsMethod();
        specificService.handleArgs(args);
    }
}

我的当前尝试测试它的方法如下:
@Mock
private SpecificService specificService
@InjectMocks
private SomeLogic someLogic;

@Test
public void testAction() {
    someLogic.action();
    verify(specificService).handleArgs(anySet());
}

但我希望确保handleArgs()接收到我期望的字符串集合。如何修改验证以检查handleArgs是否使用了“first”,“second”这组集合?谢谢。

3个回答

11

Isah给出了一个有效的答案,但我想让你注意Mockito的一个更普遍的特性,即ArgumentCaptor

在你的情况下,你应该按照以下方式操作:

Class<HashSet<String>> setClass = (Class<HashSet<String>>)(Class)HashSet.class;
ArgumentCaptor<Set<String>> setCaptor= ArgumentCaptor.forClass(setClass .class);

verify(specificService).create(setCaptor.capture());
HashSet<String> capturedSet = setCaptor.getValue();

//do whatever test you want with capturedSet

1
在这种情况下,可能有些过度设计,但你可以大致了解这是一个更通用的解决方案 :) - geoand

10

在调用测试方法之前,先准备好您的Set参数。

    @Test
    public void testAction() {
        Set<String> expectedParams = new HashSet(Arrays.asList("first", "second");
        //call tested method
        verify(specificService).handleArgs(expectedParams);
    }

谢谢,我原以为需要使用Hamcrest方法,但解决方案实际上更简单。 - me1111
不客气。我使用 Hamcrest,因为它具有更好的匹配器和更好的报告功能,当测试失败时。 - isah

9

如果你想确认集合恰好包含你指定的两个项,那么isah的解决方案非常完美;Mockito默认使用.equals进行比较,而Set.equals被定义为引用任意顺序中的相等元素。

对于更灵活的“包含”测试,可以匹配您的问题标题且允许超出期望值的集合成员。您还可以使用Hamcrest的contains匹配器

someLogic.action();
verify(specificService).handleArgs(argThat(contains("first", "second")));

至少,应该是这样的。不幸的是,argThat从Matcher中推断出它的返回类型,而Matcher又从参数中推断其返回类型,因此Java认为您的第一个参数不是一个Set<String>,而是一个Iterable<capture#1-of ? extends String>。您需要显式转换并抑制警告才能使其正常工作:

// requires @SuppressWarnings("unchecked")
verify(specificService).handleArgs(
    (Set<String>) argThat(contains("first", "second")));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接