【问题标题】:How to stub varargs in Mockito to match only one argument如何在 Mockito 中存根 varargs 以仅匹配一个参数
【发布时间】:2019-03-18 12:45:51
【问题描述】:

我想存根一些代码,以便当参数之一与特定值匹配时,可变参数方法返回 true。例如,给定我无法更改的现有代码:

(这里使用 Kotlin,但我认为这适用于任何 Java 情况。)

class Foo {
    fun bar(vararg strings : String) : Boolean {
        // Iterates `strings` and returns true when one satisfies some criteria
    }
}

...我想写类似这样的存根代码:

val foo = Foo()
whenever(foo.bar(eq("AAA"))).thenReturn(true)

当调用准确foo.bar("AAA")时,这可以正常工作。

但是,有时被测代码会调用foo.bar("AAA", "BBB"),在这种情况下,它会失败。

如何修改我的存根代码,以便在调用中传递任意数量的可变参数时它可以工作?

编辑标记为可能的duplicate;在这种情况下,该场景考虑在调用中完全省略可变参数。在这里,我试图匹配可变参数数组的一个特定元素。

【问题讨论】:

    标签: java kotlin mockito


    【解决方案1】:

    你必须对你的方法存根 2 次。首先是最不具体的存根:

    val foo = Foo()
    whenever(foo.bar(any())).thenReturn(false) // or whatever you want to return/throw here
    

    然后是更具体的单参数方法:

    whenever(foo.bar(eq("AAA"))).thenReturn(true)
    

    在您发表评论后,您也可以使用类似这样的东西(这次使用 Java):

    when(foo.bar(any())).thenAnswer(invocation -> {
        for (Object argument : invocation.getArguments()) {
            if ("AAA".equals(argument)) return true;
        }
        return false;
    });
    

    在 Kotlin 中也是如此

    whenever(foo.bar(any()).thenAnswer {
        it.arguments.contains("AAA")
    }
    

    【讨论】:

    • 谢谢!但是,这不适用于我的情况。只要“AAA”是参数之一,它就应该返回真。它不必是调用中唯一且唯一的参数。
    • @Hugh 查看我的编辑,您可以随时迭代参数,然后检查 "AAA" 是否是其中之一
    • 谢谢@Lino!完美运行。我有一个待编辑的同行评审,其中添加了您的解决方案的 Kotlin 版本。
    • @Hugh 我批准了你的编辑,但删除了你的“谢谢”cmets,因为你不应该把它放在答案中。但很高兴我能帮助你:)
    【解决方案2】:

    您可以创建自己的matcher

    public class MyVarargMatcher extends ArgumentMatcher<String[]> implements VarargMatcher
    {
        private String expectedFirstValue;
    
        public MyVarargMatcher(String expectedFirstValue)
        {
            this.expectedFirstValue = expectedFirstValue;
        }
    
        @Override
        public boolean matches(Object varargArgument) {
            if (varargArgument instanceof String[])
            {
                String[] args = (String[]) varargArgument;
                return Stream.of(args).anyMatch(expectedFirstValue::equals);
            }
            return false;
        }
    }
    

    然后像这样使用它(Java 代码):

    Foo foo = Mockito.mock(Foo.class);
    Mockito.doReturn(true).when(foo).bar(Mockito.argThat(new MyVarargMatcher("AAA")));
    

    用操作员的评论编辑:只要“AAA”是参数之一,它应该返回true

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-08-13
      • 1970-01-01
      • 2016-08-20
      • 2011-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多