Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/323.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Mockito-使用Varargs参数模拟重载方法_Java_Unit Testing_Junit_Mockito - Fatal编程技术网

Java Mockito-使用Varargs参数模拟重载方法

Java Mockito-使用Varargs参数模拟重载方法,java,unit-testing,junit,mockito,Java,Unit Testing,Junit,Mockito,当其中一个方法使用varargs时,当我们需要模拟重载方法时,Mockito很难使用。从Spring的 REST模板 中考虑下面的方法 void put(String url, Object request, Object... uriVariables) throws RestClientException; void put(String url, Object request, Map<String, ?> uriVariables) throws RestClientExc

当其中一个方法使用varargs时,当我们需要模拟重载方法时,Mockito很难使用。从Spring的<代码> REST模板

中考虑下面的方法
void put(String url, Object request, Object... uriVariables) throws RestClientException;

void put(String url, Object request, Map<String, ?> uriVariables) throws RestClientException;
void put(字符串url、对象请求、对象变量)抛出RestClientException;
void put(字符串url、对象请求、映射变量)抛出RestClientException;
模拟第二个方法很简单,但是模拟第一个方法是不可能的,因为使用
any()
将导致匹配两个方法的方法调用不明确,并且没有其他方法可以只匹配
对象…


作为问答分享解决方案,我是在付出一些努力后到达的,目的是帮助那些同舟共济的人。欢迎所有其他备选方案。

可以尝试通过使用该功能向模拟提供
defaultAnswer
来解决此问题。defaultAnswer将评估调用是否针对特定的方法并执行所需的操作,如果所需的方法不是目标,则让调用遵循自然流

这可以用一个例子很好地解释。考虑下面类中的两种重载方法:

public class StringConcat {
    public String concatenate(int i, String... strings) {
        return i + Arrays.stream(strings).collect(Collectors.joining(","));
    }

    public String concatenate(int i, List<String> strings) {
        return i + strings.stream().collect(Collectors.joining(","));
    }
}
为了表示vararg,我们没有
anyVararg()
方法(已弃用且不起作用,不确定它是否在旧版本中起作用)。但同样可以通过使用defaultAnswer创建模拟来处理,如下所示:

StringConcat stringConcat = mock(StringConcat.class);
when(stringConcat.concatenate(anyInt(), anyList())).thenReturn("hardcoded value");
@Test
void testWithDefaultAnswer(){
    // Creating mock object with default answer
    StringConcat stringConcat = mock(StringConcat.class, invocation -> {
        Method method = invocation.getMethod();
        if (method.getName().contains("concatenate") && 
               method.getParameters()[method.getParameters().length-1].isVarArgs()){
            if(invocation.getArguments().length>=method.getParameterCount()){
                List varArgParams = Arrays.stream(invocation.getArguments())
                          .skip(method.getParameterCount()-1)
                          .collect(Collectors.toList());
                return invocation.getArguments()[0]+":"
                      +varArgParams.toString(); // mocked result when varargs provided
            }
            return ""+invocation.getArguments()[0]; // mocked result when varargs not provided
        }
        return Answers.RETURNS_DEFAULTS.answer(invocation); // Ensures seamless mocking of any other methods
    });

    // Mock any non varargs methods as needed
    when(stringConcat.concatenate(anyInt(), anyList())).thenReturn("hardcoded"); // mocking as usual

    // Test the mocks
    System.out.println(stringConcat.concatenate(1, "a", "b")); // default answer based mock, with varargs provided
    System.out.println(stringConcat.concatenate(1)); // default answer based mock, without varargs provided
    System.out.println(stringConcat.concatenate(1, Lists.newArrayList("a", "b"))); // mocked non varargs method
}
输出:

1:[a, b]
1
hardcoded

你使用的Mockito版本是什么?它的2.21.0版本在项目创建时就已经使用了,但是看看最新的文档,情况看起来还是一样的。