我有一个看起来有点像这样的 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
.
当我运行这个测试时,匹配器被调用了两次。这导致一个BufferUnderflowException
.
现在,我可以通过让匹配器在matchesSafely
调用开始时存储缓冲区位置并将位置移回最后的位置(在 finally 块中)来解决这个问题,但在我看来,我的匹配器不应该被叫了两次。
任何人都可以对此有所了解吗?
编辑#1:
可能值得注意的是,缓冲区在被传递到通道之前被翻转,因此位置为 0,并且限制设置为写入的数据量。
我已经调试了测试,并且匹配器肯定被调用了两次。
我可以通过在开头标记缓冲区并在结尾重置它来使测试通过matchesSafely()
,因此第二次通过匹配器读取相同的数据。这也证实了匹配器被调用了两次,否则它仍然会失败。
编辑#2:
所以看起来这是 Mockito 框架的预期行为。回想起来,我的匹配器有点差,因为它修改了全局状态。我已经修改了匹配器以记录起始位置并在方法结束时返回它matchesSafely()
。无论如何,这可能是一个好主意,因为它可以节省修改全局状态。我不使用mark()
和reset()
出于同样的原因。