你可以通过一种简单的方式让它工作:
when(stream.read()).thenReturn(0, 1, 2, 3 /* ... */);
也就是说,现在,您正在嘲笑亚马逊的实施。这意味着如果任何方法变成 final,你的状态就会很糟糕,因为 Mockito 由于编译器的限制不支持模拟 final 方法。模拟您不拥有的类型很诱人,但可能会导致损坏。
如果您的目标是测试 getBytes 是否返回正确的值并关闭其流,则更稳定的方法可能是重构以使用任意 InputStream:
class MyObject {
public byte[] getBytes(File f, int offset, int length) {
/* ... */
// Delegate the actual call to a getBytes method.
return getBytes(s3ObjectInputStream, f, offset, length);
}
/** Call this package-private delegate in tests with any arbitrary stream. */
static byte[] getBytes(InputStream s, File f, int offset, int length) {
/* ... */
}
}
此时,您可以使用spy(new ByteArrayInputStream(YOUR_BYTE_ARRAY)) 对其进行测试,并通过调用verify(stream).close() 来完成一个非常引人注目的测试。
按照这些思路,另一种解决方案是添加一个您可以控制的接缝,从远处有效地包裹getBytes:
class MyObject {
public byte[] getBytes(File f, int offset, int length) {
/* ... */
InputStream inputStream = getStream(response.getObjectContent());
/* ... */
}
/** By default, just pass in the stream you already have. */
InputStream getStream(S3ObjectInputStream s3Stream) {
return s3Stream;
}
}
class MyObjectTest {
@Test public void yourTest() {
/* ... */
MyObject myObject = new MyObject(client) {
/** Instead of returning the S3 stream, insert your own. */
@Override InputStream getStream() { return yourMockStream; }
}
/* ... */
}
}
但请记住,您是在测试您认为 Amazon S3 应该工作的方式,而不是它在实践中是否继续工作。如果您的目标是“测试从 [S3] 打开流”,那么针对实际 S3 实例运行的集成测试可能是一个好主意,以弥补 S3 模拟和实际 S3 之间的差距。