回答:
さらに、@ 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
はモックであり、現在定義されているため、doSomething()
実際には何も実行せず、渡されたオブジェクトを記録するだけです。つまり、doSomething
実行される前にそのままキャプチャされます。
verify
、times(1)
がデフォルトであり、省略できます。
verify
メソッドを呼び出すと、その情報を使用して、実行している検証に対して照合が実行されます。すべてのパラメータについて、チェックする特定の呼び出しと一致するかどうかを尋ねます。ArgumentCaptorがチェックされると、それは呼び出された値を格納するだけなので、verify
終了すると、関連するすべての呼び出しを保持します。おおよその動作です。それがお役に立てば
主な2つの違いは次のとおりです。
ArgumentCaptor
は複数回キャプチャできます。後者を説明するために、あなたが持っているとしましょう:
final ArgumentCaptor<Foo> captor = ArgumentCaptor.forClass(Foo.class);
verify(x, times(4)).someMethod(captor.capture()); // for instance
その後、キャプターは4つの引数すべてにアクセスできるようになり、その後、個別にアサーションを実行できます。
実際には、これは任意の数の引数VerificationMode
です。いずれにせよ、キャプターは必要に応じてそれらすべてにアクセスできます。
これには、ArgumentMatcher
特にmockitoとassertjを組み合わせた場合に、独自のs を実装する必要があるよりも、そのようなテストを(imho)作成する方がはるかに簡単であるという利点もあります。
JUnitの代わりにTestNGを使用することを検討してください。
完全なチェックを行うための手順は次のとおりです。
キャプターを準備します。
ArgumentCaptor<SomeArgumentClass> someArgumentCaptor = ArgumentCaptor.forClass(SomeArgumentClass.class);
依存コンポーネント(テスト対象のコラボレーター)times(1)への呼び出しがデフォルト値であることを確認してください。したがって、追加する必要があります。
verify(dependentOnComponent, times(1)).send(someArgumentCaptor.capture());
コラボレーターに渡される引数を取得します
SomeArgumentClass someArgument = messageCaptor.getValue();
someArgumentはアサーションに使用できます
ここでは、1つのコールバックメソッドの適切な例を示します。メソッド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
実行されますか?