簡體   English   中英

Mockito - 使用 Varargs 參數模擬重載方法

[英]Mockito - Mocking overloaded methods with Varargs parameters

當我們需要在其中一個使用可變參數時模擬重載方法時,Mockito 很難使用。 考慮 Spring 的RestTemplate的以下方法

void put(String url, Object request, Object... uriVariables) throws RestClientException;

void put(String url, Object request, Map<String, ?> uriVariables) throws RestClientException;

模擬第二個是直接的,但模擬第一個是不可能的,因為使用any()會導致一個不明確的方法調用匹配這兩個方法,並且沒有其他方法可以只匹配Object...

將解決方案作為問答分享,這是我在努力之后到達的,以幫助那些在同一條船上的人。 歡迎所有其他選擇。

可以通過使用該功能為模擬提供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(","));
    }
}

可以使用 Mockito 模擬第二種方法,如下所示:

StringConcat stringConcat = mock(StringConcat.class);
when(stringConcat.concatenate(anyInt(), anyList())).thenReturn("hardcoded value");

為了表示可變參數,我們沒有anyVararg()方法(已棄用且不起作用,不確定它是否適用於舊版本)。 但是同樣可以通過使用 defaultAnswer 創建模擬來處理,如下所示:

@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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM