次のような Mockito テストがあります (もちろん単純化されています)。
@RunWith(MockitoJUnitRunner.class)
public class BlahTest {
private static final int VERSION = 41;
private static final int PAGE_SIZE = 4096;
@Mock private FileChannel channel;
@Test
public void shouldWriteStandardHeader() throws Exception {
final Blah blah = new Blah(channel, VERSION, PAGE_SIZE);
blah.create();
verify(channel).write(littleEndianByteBufferContaining(Blah.MAGIC_NUMBER,
VERSION,
PAGE_SIZE));
}
private ByteBuffer littleEndianByteBufferContaining(final int... ints) {
return argThat(byteBufferMatcher(ints));
}
private Matcher<ByteBuffer> byteBufferMatcher(final int... ints) {
return new TypeSafeMatcher<ByteBuffer>() {
@Override
public void describeTo(final Description description) {
description.appendText("a little-endian byte buffer containing integers ").
appendValueList("", ",", "", ints);
}
@Override
protected boolean matchesSafely(final ByteBuffer buffer) {
if (buffer.order() != ByteOrder.LITTLE_ENDIAN) {
return false;
}
for (final int i : ints) {
if (buffer.getInt() != i) {
return false;
}
}
return true;
}
};
}
}
基本的に、このテストは、Blah.create()
が呼び出されたときにByteBuffer
、特定のデータを含む をに書き込むことをアサートしようとしていFileChannel
ます。
このテストを実行すると、マッチャーが 2 回呼び出されます。これにより、BufferUnderflowException
.
これで、呼び出しの開始時にマッチャーにバッファー位置を保存matchesSafely
させ、最後に (finally ブロックで) その位置に戻すことでこれを回避できましたが、私のマッチャーはそうすべきではないように思えます。 2回呼び出されます。
誰でもこれに光を当てることができますか?
編集#1:
チャネルに渡される前にバッファーが反転されることに注意してください。そのため、位置は 0 であり、制限は書き込まれたデータの量に設定されます。
テストをデバッグしましたが、マッチャーは間違いなく 2 回呼び出されています。
バッファーを最初にマークし、最後にリセットすることでテストに合格できるmatchesSafely()
ので、マッチャーの 2 回目のパスで同じデータが読み取られます。これにより、マッチャーが 2 回呼び出されていることも確認できます。
編集#2:
したがって、これは Mockito フレームワークの予想される動作のようです。振り返ってみると、グローバル状態を変更するため、私のマッチャーは少し貧弱です。マッチャーを変更して、開始位置を記録し、matchesSafely()
メソッドの最後でそこに戻るようにしました。グローバル状態の変更を保存するため、これはおそらく良い考えです。私は同じ理由でmark()
andを使用しません。reset()