我有一个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;
}
};
}
}
Run Code Online (Sandbox Code Playgroud)
本质上,这个测试试图断言在Blah.create()调用时,它会将ByteBuffer包含某些数据的内容写入FileChannel.
当我运行此测试时,匹配器会被调用两次.这导致了BufferUnderflowException.
现在,我可以通过让匹配器在matchesSafely调用开始时存储缓冲区位置并将位置移回到最后位置(在最后一个块中)来解决这个问题,但在我看来我的匹配器不应该被叫两次.
任何人都可以对此有所了解吗?
编辑#1:
值得注意的是缓冲区在传递到通道之前被翻转,因此位置为0,并且限制设置为写入的数据量.
我调试了测试,匹配器肯定会被调用两次.
我可以通过在开始时标记缓冲区matchesSafely()并在结束时重置它来使测试通过,因此第二次通过匹配器读取相同的数据.这也证实了匹配器被调用两次,否则它仍会失败.
编辑#2:
所以看起来这是Mockito框架的预期行为.回想起来,我的匹配器有点差,因为它修改了全局状态.我已经修改了匹配器以记录起始位置并在matchesSafely()方法结束时寻找它.无论如何,这可能是个好主意,因为它可以节省修改全局状态.我没有使用mark()并reset()出于同样的原因.
我不认为匹配器被调用两次,您只需要rewind在缓冲区中读取数据即可:
protected boolean matchesSafely(final ByteBuffer buffer) {
if (buffer.order() != ByteOrder.LITTLE_ENDIAN) {
return false;
}
buffer.rewind();
...
}
Run Code Online (Sandbox Code Playgroud)
更新
因此,看起来它实际上确实被调用了两次。最终,这一切都发生在verify方法中。如果您查看Mockito的源代码,那么有一种Times.verify方法实际上可以验证两件事:
Mockito包含channel模拟对象上所有方法的实际调用列表。为了验证这些调用中的哪一个是正确的,它会将每个调用与匹配器进行匹配。它实际上执行了两次。请查看来源以了解整个想法。
我不确定这是否是错误,您应该询问Mockito开发人员。我建议它不会rewind在matchesSafely每次解决问题时都对方法中的缓冲区造成伤害-它不应该损害正确性。
| 归档时间: |
|
| 查看次数: |
1480 次 |
| 最近记录: |