답변:
@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);
OtherClass
mock은 모의이며, 현재 정의 된대로 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 개의 모든 인수에 대한 액세스 권한을 부여 할 수 있으며이를 통해 개별적으로 어설 션을 수행 할 수 있습니다.
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)
captor
귀하의 답변에서 어디에 정의되어 있습니까?
doSomething(data)
변이innerData
, 그 변화가 존재할 것이다assertEquals("Some inner data", actual.innerData)
또는 것innerData
그대로 캡쳐 전에doSomething
실행?