[英]Example of Mockito's argumentCaptor
谁能给我提供一个示例,说明如何使用org.mockito.ArgumentCaptor
class 以及它与 mockito 提供的简单匹配器有何不同。
我阅读了提供的 mockito 文档,但这些文档并没有清楚地说明,没有一个能够清楚地解释它。
我同意@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);
两个主要区别是:
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<ArgumentClass> argumentCaptor = ArgumentCaptor.forClass(ArgumentClass.class);
其次,验证对依赖组件(被测对象的合作者)的调用。
times(1) 是默认值,所以需要添加它。
verify(dependentOnComponent, times(1)).method(argumentCaptor.capture());
第三,使用捕获者的 getValue() 获取传递给合作者的参数
ArgumentClass someArgument = messageCaptor.getValue();
四、使用 someArgument 进行断言
我创建了这个示例来模拟一个非常简单的服务,该服务使用存储库保存字符串(无依赖注入,无实体),只是为了快速教授 ArgumentCaptor。
3 个类:PersonService、PersonRepository 和 PersonServiceTest(省略包)
public class PersonService {
private PersonRepository personRepository;
public void setPersonRepository(final PersonRepository personRepository) {
this.personRepository = personRepository;
}
public void savePerson(final String name) {
this.personRepository.save(name.toUpperCase().trim());
}
}
public class PersonRepository {
public void save(final String person) {
System.out.println(".. saving person ..");
}
}
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
class PersonServiceTest {
@Test
void testPersonService() {
// Create the repository mock
final PersonRepository personRepositoryMock = mock(PersonRepository.class);
// Create the service and set the repository mock
final PersonService personService = new PersonService();
personService.setPersonRepository(personRepositoryMock);
// Save a person
personService.savePerson("Mario ");
// Prepare an ArgumentCaptor to capture the value passed to repo.saveMethod
final ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
// Capture the argument passed in the unique method invocation
verify(personRepositoryMock, times(1)).save(captor.capture());
// Check if the captured value is the expected one
final String capturedParameter = captor.getValue();
assertEquals("MARIO", capturedParameter);
}
}
您可能希望将 verify() 与 ArgumentCaptor 结合使用以确保在测试中执行,并使用 ArgumentCaptor 来评估 arguments:
ArgumentCaptor<Document> argument = ArgumentCaptor.forClass(Document.class);
verify(reader).document(argument.capture());
assertEquals(*expected value here*, argument.getValue());
参数的值显然可以通过 argument.getValue() 访问,以进行进一步的操作/检查或任何您想做的事情。
对此和大多数事情使用注释@Spy、@Mock、@Captor 等。
这是一个示例(使用 JUnit 5):
public class Blam
{
public void foo(final OtherClass other)
{
final SomeData data = new SomeData("Some inner data");
other.doSomething(data);
}
}
@ExtendWith(MockitoExtension.class)
public class TestBlam
{
@Captor
private ArgumentCaptor<SomeData> captorSomeData;
private Blam classToTest;
@Mock
private OtherClass mockOtherClass;
@BeforeEach
void beforeEach()
{
classToTest = new Blam();
}
@Test
void foo_allGood_success()
{
SomeData actualSomeData;
classToTest.foo(mockOtherClass);
verify(mockOtherClass).doSomething(captorSomeData.capture());
actualSomeData = captorSomeData.getValue();
assert(stuff about actualSomeData);
}
}
在这里,我给你一个回调方法的正确例子。 所以假设我们有一个类似方法 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)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.