누구든지 org.mockito.ArgumentCaptor
수업 사용 방법 과 mockito와 함께 제공되는 간단한 매처 와 다른 점 을 보여주는 예를 제공해 주 시겠습니까?
제공된 mockito 문서를 읽었지만 그 내용을 명확하게 설명하지는 못하며 명확하게 설명 할 수는 없습니다.
답변
@fge가 말한 것에 더 동의합니다. 예를 보자. 방법이 있다고 생각하십시오.
class A {
public void foo(OtherClass other) {
SomeData data = new SomeData("Some inner data");
other.doSomething(data);
}
}
내부 데이터를 확인하려면 captor를 사용할 수 있습니다.
// 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 개의 모든 인수에 대한 액세스 권한을 부여 할 수 있으며이를 통해 개별적으로 어설 션을 수행 할 수 있습니다.
a 또는 VerificationMode
고정 된 수의 호출에 국한되지 않기 때문에,이 또는 임의의 수의 인수 ; 어쨌든, 캡터는 원한다면 그들 모두에게 접근 권한을 부여 할 것입니다.
이것은 또한 자신 ArgumentMatcher
의 구현을 수행하는 것보다, 특히 mockito와 assertj를 결합하는 경우 보다 그러한 테스트를 작성하는 것이 훨씬 쉽다는 이점이 있습니다 .
아, JUnit 대신 TestNG 사용을 고려하십시오.
답변
전체 확인을위한 단계는 다음과 같습니다.
체포 자 준비 :
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)