ユニットテストでメソッド呼び出しをカウントする最良の方法は何ですか。テストフレームワークで許可されているものはありますか?
モックフレームワークが通常提供する.expects(1)タイプのメソッドを使用したいと思うかもしれません。
Mockitoを使用して、リストをテストしていて、clearが3回呼び出され、addがこれらのパラメーターで少なくとも1回呼び出されたことを確認したい場合は、次のようにします。
List mock = mock(List.class);
someCodeThatInteractsWithMock();
verify(mock, times(3)).clear();
verify(mock, atLeastOnce()).add(anyObject());
( http://code.google.com/p/mockito/wiki/MockitoVSEasyMock から)
Mockitoでは、次のようなことができます。
YourService serviceMock = Mockito.mock(YourService.class);
// code using YourService
// details of all invocations including methods and arguments
Collection<Invocation> invocations = Mockito.mockingDetails(serviceMock).getInvocations();
// just a number of calls of any mock's methods
int numberOfCalls = invocations.size();
MockitoのインターフェイスAnswerを使用して、メソッド呼び出しの数をカウントできます。
ConnectionPool mockedConnectionPool = mock(ConnectionPool.class);
final int[] counter = new int[1];
when(mockedConnectionPool.getConnection()).then(new Answer<Connection>() {
@Override
public Connection answer(InvocationOnMock invocation) throws Throwable {
counter[0]++;
return conn;
}
});
// some your code
assertTrue(counter[0] == 1);
ロールを返す単一のメソッド「getRole(String user)」を持つサンプルクラス「RoleRepository」が与えられます。
このオブジェクトをMockまたはSpyとして宣言し、getRole(String)メソッドが1回呼び出されるかどうかを確認するとします。
あなたは次のようなことをするでしょう:Mockito.verify(roleRepository, Mockito.times(1)).getRole(Mockito.anyString());
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.Spy;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class RoleRepositoryTest {
@Spy
private RoleRepository roleRepository = new RoleRepository();
@Test
public void test() {
roleRepository.getRole("toto");
Mockito.verify(roleRepository, Mockito.times(1)).getRole(Mockito.anyString());
}
public static class RoleRepository {
public String getRole(String user) {
return "MyRole";
}
}
}
カウントするメソッドに応じて、クラス/パッケージ/メソッドに一致する@Before
アドバイスを使用して、テスト構成を作成できます。
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class MethodCounterAspect {
private int counter = 0 // or inject the Counter object into this aspect
@Pointcut( "execution( * com.sample.your.package.*.*(..) )" )
public void methodsToCount() {}
@Before("methodsToCount()")
public void execute() throws Throwable {
counter++; // or update the counter injected into this aspect..
}
// get the counter
}
簡単な場合は、上記またはXML構成を介してVanilla AspectJまたはSpring AOPを使用できます。
必要に応じて、異なるポイントカット/アスペクトを作成できます。
test spy が必要なようです。たとえば、 Mockito.spy() を参照してください。
いくつかのオプションがあります
1)関数内の呼び出しをカウントする特別なコードを追加します。それは動作しますが、それは素晴らしい解決策ではありません。
2)単体テストを実行した後、コードカバレッジを確認します。ほとんどのカバレッジツールは呼び出しをカウントしますが、実際には後処理用に設計されています。
3)プロファイラーを使用します。プロファイラーを使用すると、関数が呼び出された回数をカウントできます。これは非常に手動のプロセスであるため、単体テスト用に実際には設計されていません。
より良い解決策は、出力が内部でどのように機能するかをチェックするのではなく、出力が期待どおりであることをチェックすることです。