[英]Mockito. Verify method arguments
我用谷歌搜索過這個,但沒有找到任何相關的東西。 我有這樣的事情:
Object obj = getObject();
Mockeable mock= Mockito.mock(Mockeable.class);
Mockito.when(mock.mymethod(obj )).thenReturn(null);
Testeable testableObj = new Testeable();
testableObj.setMockeable(mock);
command.runtestmethod();
現在,我想驗證在runtestmethod()
內部調用的mymethod(Object o)
是使用 Object o
調用的,而不是其他任何方法。 但是我總是通過測試,無論我進行什么驗證,例如:
Mockito.verify(mock.mymethod(Mockito.eq(obj)));
要么
Mockito.verify(mock.mymethod(Mockito.eq(null)));
要么
Mockito.verify(mock.mymethod(Mockito.eq("something_else")));
我總是通過考試。 我如何完成該驗證(如果可能)?
謝謝你。
ArgumentMatcher
的替代品是ArgumentCaptor
。
官方示例:
ArgumentCaptor<Person> argument = ArgumentCaptor.forClass(Person.class);
verify(mock).doSomething(argument.capture());
assertEquals("John", argument.getValue().getName());
還可以使用@Captor注釋定義捕獲器:
@Captor ArgumentCaptor<Person> captor;
//... MockitoAnnotations.initMocks(this);
@Test public void test() {
//...
verify(mock).doSomething(captor.capture());
assertEquals("John", captor.getValue().getName());
}
您是否嘗試使用對象的 .equals 方法進行邏輯相等? 您可以使用 Mockito 中包含的 argThat 匹配器來執行此操作
import static org.mockito.Matchers.argThat
接下來,您可以實現自己的參數匹配器,該匹配器將遵循每個對象的 .equals 方法
private class ObjectEqualityArgumentMatcher<T> extends ArgumentMatcher<T> {
T thisObject;
public ObjectEqualityArgumentMatcher(T thisObject) {
this.thisObject = thisObject;
}
@Override
public boolean matches(Object argument) {
return thisObject.equals(argument);
}
}
現在使用您的代碼,您可以更新它以閱讀...
Object obj = getObject();
Mockeable mock= Mockito.mock(Mockeable.class);
Mockito.when(mock.mymethod(obj)).thenReturn(null);
Testeable obj = new Testeable();
obj.setMockeable(mock);
command.runtestmethod();
verify(mock).mymethod(argThat(new ObjectEqualityArgumentMatcher<Object>(obj)));
如果你只是想要完全相等(內存中的同一個對象),那就做
verify(mock).mymethod(obj);
這將驗證它是否被調用過一次。
eq
匹配器。.verify(mock)
。 您現在正在對方法調用的結果進行驗證,而不驗證任何內容(不進行方法調用)。 因此,所有測試都通過了。您的代碼應如下所示:
Mockito.verify(mock).mymethod(obj);
Mockito.verify(mock).mymethod(null);
Mockito.verify(mock).mymethod("something_else");
argThat
加上 lambda這就是您無法通過參數驗證的方式:
verify(mock).mymethod(argThat(
(x)->false
));
在哪里
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.verify;
argThat
加上斷言上面的測試會“說” Expected: lambda$... Was: YourClass.toSting...
。 如果在 lambda 中使用斷言,您可以獲得更具體的失敗原因:
verify(mock).mymethod(argThat( x -> {
assertThat(x).isNotNull();
assertThat(x.description).contains("KEY");
return true;
}));
❗️但是❗️:這僅在
true
)。 如果已驗證的方法調用了 2+ 次,mockito 會將所有調用的組合傳遞給每個驗證器。 因此, mockito 期望您的驗證器靜默地為參數 set 之一返回true
,並為其他有效調用返回false
(無斷言異常)。 這種期望對於 1 次方法調用來說不是問題 - 它應該只返回 true 1 次。
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.verify;
現在失敗的測試會說: Expected: Obj.description to contain 'KEY'. Was: 'Actual description'
Expected: Obj.description to contain 'KEY'. Was: 'Actual description'
。 注意:我使用了assertJ
斷言,但使用哪個斷言框架取決於您。
argThat
帶有多個參數。 如果您使用argThat
,則必須為所有參數提供匹配項。 例如,如果您有另一個帶有 2 個參數的方法:
verify(mock).mymethod2(eq("VALUE_1"), argThat((x)->false));
// above is correct as eq() is also an argument matcher.
verify(mock).mymethod2("VALUE_1", argThat((x)->false));
// above is incorrect; an exception will be thrown, as the first arg. is given without an argument matcher.
在哪里:
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
eq
器檢查參數是否相等的最簡單方法:
verify(mock).mymethod(eq(expectedValue));
// NOTE: ^ where the parentheses must be closed.
如果通過 ref 進行比較是可以接受的,那么繼續:
verify(mock).mymethod(expectedArg);
// NOTE: ^ where the parentheses must be closed.
原始問題失敗的verify(mock.mymethod...
原因是括號的錯誤位置: verify(mock.mymethod...
那是錯誤的。正確的是: verify(mock).*
我以這種方式使用了 Mockito.verify
@UnitTest
public class JUnitServiceTest
{
@Mock
private MyCustomService myCustomService;
@Test
public void testVerifyMethod()
{
Mockito.verify(myCustomService, Mockito.never()).mymethod(parameters); // method will never call (an alternative can be pick to use times(0))
Mockito.verify(myCustomService, Mockito.times(2)).mymethod(parameters); // method will call for 2 times
Mockito.verify(myCustomService, Mockito.atLeastOnce()).mymethod(parameters); // method will call atleast 1 time
Mockito.verify(myCustomService, Mockito.atLeast(2)).mymethod(parameters); // method will call atleast 2 times
Mockito.verify(myCustomService, Mockito.atMost(3)).mymethod(parameters); // method will call at most 3 times
Mockito.verify(myCustomService, Mockito.only()).mymethod(parameters); // no other method called except this
}
}
您是否檢查過可模擬類的 equals 方法? 如果這個總是返回 true 或者你針對同一個實例測試同一個實例並且 equal 方法沒有被覆蓋(因此只檢查引用),那么它返回 true。
另一種方法是使用 org.mockito.internal.matchers.Equals.Equals 方法而不是重新定義一個:
verify(myMock).myMethod((inputObject)Mockito.argThat(new Equals(inputObjectWanted)));
您是否嘗試過使用 same() 匹配器? 如:
verify(mockObj).someMethod(same(specificInstance));
我有同樣的問題。 我用 eq() 匹配器和 refEq() 匹配器嘗試過,但我總是有誤報。 當我使用 same() 匹配器時,當參數是不同的實例時測試失敗,並且一旦參數是相同的實例就通過了。
Verify(a).aFunc(eq(b))
在偽代碼中:
在實例
a
- 調用名為aFunc
的函數時。驗證此調用有一個等於
b
的參數。
上述許多答案讓我感到困惑,但我懷疑這可能是由於舊版本的 Mockito。 這個答案是使用完成的
使用 ArgumentCaptor 我是這樣做的:
@Mock
MyClientService myClientService;
@InjectMocks
MyService myService;
@Test
void myTest() {
ArgumentCaptor<String> captorParam1 = ArgumentCaptor.forClass(String.class);
ArgumentCaptor<String> captorParam2 = ArgumentCaptor.forClass(String.class);
Mockito.when(myClientService.doSomething(captorParam1.capture(), captorParam2.capture(), ArgumentMatchers.anyString()))
.thenReturn(expectedResponse);
assertDoesNotThrow(() -> myService.process(data));
assertEquals("param1", captorParam1.getValue());
assertEquals("param2", captorParam2.getValue());
verify(myClientService, times(1))
.doSomething(anyString(), anyString(), anyString());
}
您還可以使用 TypeSafeDiagnosingMatcher
private Matcher<GetPackagesRequest> expectedPackageRequest(final AvailabilityRequest request) {
return new TypeSafeDiagnosingMatcher<GetPackagesRequest>() {
StringBuilder text = new StringBuilder(500);
@Override
protected boolean matchesSafely(GetPackagesRequest req, Description desc) {
String productCode = req.getPackageIds().iterator().next().getValue();
if (productCode.equals(request.getSupplierProductCode())) {
text.append("ProductCode not equal! " + productCode + " , " + request.getSupplierProductCode());
return true;
}
text.append(req.toString());
return false;
}
@Override
public void describeTo(Description d) {
d.appendText(text.toString());
}
};
}
然后驗證該調用:
Mockito.verify(client).getPackages(Mockito.argThat(expectedPackageRequest(request)));
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.