Answers:
我同意@fge所说的内容,并且还要更多。让我们来看一个例子。考虑您有一个方法:
class A {
public void foo(OtherClass other) {
SomeData data = new SomeData("Some inner data");
other.doSomething(data);
}
}
现在,如果要检查内部数据,可以使用捕获器:
// Create a mock of the OtherClass
OtherClass other = mock(OtherClass.class);
// Run the foo method with the mock
new A().foo(other);
// Capture the argument of the doSomething function
ArgumentCaptor<SomeData> captor = ArgumentCaptor.forClass(SomeData.class);
verify(other, times(1)).doSomething(captor.capture());
// Assert the argument
SomeData actual = captor.getValue();
assertEquals("Some inner data", actual.innerData);
OtherClass
是一个模拟,按照现在的定义,它实际上doSomething()
不会做任何事情,它只是记录传递的对象。这意味着它将在doSomething
执行之前按原样捕获。
verify
,times(1)
是默认值,可以省略。
verify
方法时,它将使用该信息来对您正在执行的验证进行匹配。对于每个参数,它询问它是否与它检查的特定调用匹配。选中ArgumentCaptor时,它仅存储使用其调用的值,因此当verify
结束时,它将保存所有相关的调用。大致就是这样。希望对您有帮助
两个主要区别是:
ArgumentCaptor
可以捕捉更比一次。为了说明后者,请说您有:
final ArgumentCaptor<Foo> captor = ArgumentCaptor.forClass(Foo.class);
verify(x, times(4)).someMethod(captor.capture()); // for instance
然后,捕获程序将使您能够访问所有4个参数,然后可以分别对它们进行断言。
实际上,因为 VerificationMode
不限于固定数量的调用;无论如何,如果您愿意,绑架者将使您能够访问所有这些对象。
这还有一个好处,即这种测试比必须实施自己的测试更容易编写 ArgumentMatcher
的 -特别是如果您将Mockito与assertj结合使用。
哦,请考虑使用TestNG代替JUnit。
进行全面检查的步骤是:
准备捕获器:
ArgumentCaptor<SomeArgumentClass> someArgumentCaptor = ArgumentCaptor.forClass(SomeArgumentClass.class);
验证对依赖于组件(被测对象的合作者)times(1)的调用是默认值,因此需要添加它。
verify(dependentOnComponent, times(1)).send(someArgumentCaptor.capture());
将参数传递给协作者
SomeArgumentClass someArgument = messageCaptor.getValue();
someArgument可用于断言
在这里,我给您一个回调方法的正确示例。因此,假设我们有一个类似方法login()的方法:
public void login() {
loginService = new LoginService();
loginService.login(loginProvider, new LoginListener() {
@Override
public void onLoginSuccess() {
loginService.getresult(true);
}
@Override
public void onLoginFaliure() {
loginService.getresult(false);
}
});
System.out.print("@@##### get called");
}
我还将所有帮助程序类放在此处,以使示例更加清楚:loginService类
public class LoginService implements Login.getresult{
public void login(LoginProvider loginProvider,LoginListener callback){
String username = loginProvider.getUsername();
String pwd = loginProvider.getPassword();
if(username != null && pwd != null){
callback.onLoginSuccess();
}else{
callback.onLoginFaliure();
}
}
@Override
public void getresult(boolean value) {
System.out.print("login success"+value);
}}
而且我们的监听器LoginListener为:
interface LoginListener {
void onLoginSuccess();
void onLoginFaliure();
}
现在我只想测试类Login的方法login()
@Test
public void loginTest() throws Exception {
LoginService service = mock(LoginService.class);
LoginProvider provider = mock(LoginProvider.class);
whenNew(LoginProvider.class).withNoArguments().thenReturn(provider);
whenNew(LoginService.class).withNoArguments().thenReturn(service);
when(provider.getPassword()).thenReturn("pwd");
when(provider.getUsername()).thenReturn("username");
login.getLoginDetail("username","password");
verify(provider).setPassword("password");
verify(provider).setUsername("username");
verify(service).login(eq(provider),captor.capture());
LoginListener listener = captor.getValue();
listener.onLoginSuccess();
verify(service).getresult(true);
也不要忘记在测试类上方添加注释
@RunWith(PowerMockRunner.class)
@PrepareForTest(Login.class)
captor
您的答案在哪里定义?
doSomething(data)
mutateinnerData
,那么该更改会出现在中assertEquals("Some inner data", actual.innerData)
,还是会在执行之前innerData
按原样捕获?doSomething