[英]Mockito verify with list that changes
我有一個簡單的Bar
對某些字符串執行操作:
public interface Bar {
void action(List<String> strings);
}
然后我的Foo
正在測試中。 它會隨着時間的推移建立一個字符串列表,然后最終使用Bar
來處理它們。 處理完成后,隊列將被清除。
public class Foo {
private final Bar bar;
private final List<String> strings;
public Foo(Bar bar) {
this.bar = bar;
this.strings = new ArrayList<>();
}
public void addStrings(String... strings) {
Collections.addAll(this.strings, strings);
}
public void processStrings() {
bar.action(strings);
strings.clear();
}
}
我試圖驗證Bar.action
被預期的字符串調用。 然而,沒有的Mockito不檢測與實際參數的真實調用,因為調用時所使用的名單Bar.action
被事后清除。
我可能做錯了什么,但這對我來說聞起來像個臭蟲。 這是測試:
@Test
public void shouldVerify() {
// Given
Bar bar = mock(Bar.class);
Foo foo = new Foo(bar);
foo.addStrings("Hello", "World");
foo.addStrings("!!!");
// When
foo.processStrings();
// Then
verify(bar).action(Arrays.asList("Hello", "World", "!!!"));
}
比較失敗:
預期:bar.action([Hello,World,!!!]);
實際:bar.action([]);
可以肯定的是,注釋掉strings.clear()
可以讓Mockito正確驗證。
我可以通過制作一個新列表傳遞給Bar
來解決這個問題,例如:
public void processStrings() {
bar.action(new ArrayList<>(strings));
strings.clear();
}
這里不完全確定,但這似乎是Mockito的限制(但不要引用我的話)。 起初我認為這可以通過ArgumentCaptor
解決,但它捕獲相同的實例,當您驗證它時,它已經被修改。
根據這個答案,您可以使用Answer
來驗證調用方法時的參數。 由於Bar::action
的返回類型為void,因此存根需要稍微不同的方法。 Mockito文檔建議使用doX()
系列方法。
public void name() {
Bar bar = mock(Bar.class);
doAnswer(invocation -> {
Object[] args = invocation.getArguments();
List<String> list = (List<String>) args[0];
assertThat(list.size(), is(3));
return null;
}).when(bar).action(anyList());
Foo foo = new Foo(bar);
foo.addStrings("Hello", "World");
foo.addStrings("!!!");
foo.processStrings();
}
在doAnswer
塊中,您可以在將列表傳遞給模擬時訪問該列表。 斷言可以在那里完成,或者您可以存儲參數並在以后執行。 我會說解決方案不是很優雅。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.