Java 我想模拟一个扩展InputStream、模拟读取、验证关闭的专有类
我想使用Mockito来模拟AmazonS3并测试从中打开一个流 然后在我的代码读取流之后验证流是否关闭。我还想从流中读取字节。大概是这样的:Java 我想模拟一个扩展InputStream、模拟读取、验证关闭的专有类,java,unit-testing,inputstream,mockito,Java,Unit Testing,Inputstream,Mockito,我想使用Mockito来模拟AmazonS3并测试从中打开一个流 然后在我的代码读取流之后验证流是否关闭。我还想从流中读取字节。大概是这样的: AmazonS3 client = mock(AmazonS3.class); when(tm.getAmazonS3Client()).thenReturn(client); S3Object response = mock(S3Object.class); when(client.getObj
AmazonS3 client = mock(AmazonS3.class);
when(tm.getAmazonS3Client()).thenReturn(client);
S3Object response = mock(S3Object.class);
when(client.getObject(any(GetObjectRequest.class))).thenReturn(response);
S3ObjectInputStream stream = mock(S3ObjectInputStream.class);
when(response.getObjectContent()).thenReturn(stream);
somehow mock the read method
MyObject me = new MyObject(client);
byte[] bra me.getBytes(File f, offset, length);
assertEquals(length, bra.length);
verify(stream).close();
您可以通过一种简单的方式实现这一点:
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(新的ByteArrayInputStream(您的字节数组))
对其进行测试,并通过调用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; }
}
/* ... */
}
}
不过,请记住,您正在测试您认为AmazonS3应该如何工作,而不是它在实践中是否继续工作。如果您的目标是“测试从[S3]打开一个流”,那么针对实际S3实例运行的集成测试可能是一个好主意,以弥补S3模拟与S3之间的差距。您可能可以通过一种简单的方式实现这一点:
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(新的ByteArrayInputStream(您的字节数组))
对其进行测试,并通过调用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; }
}
/* ... */
}
}
不过,请记住,您正在测试您认为AmazonS3应该如何工作,而不是它在实践中是否继续工作。如果您的目标是“测试从[S3]打开一个流”,那么针对实际S3实例运行的集成测试可能是一个好主意,以弥补S3模拟与S3之间的差距。您可以使用Mockito的答案模拟流
String expectedContents = "Some contents";
InputStream testInputStream = new StringInputStream(expectedContents);
S3ObjectInputStream s3ObjectInputStream = mock(S3ObjectInputStream.class);
S3Object s3Object = mock(S3Object.class);
AmazonS3Client amazonS3Client = mock(AmazonS3Client.class);
S3AttachmentsService service = new S3AttachmentsService(amazonS3Client);
when(s3ObjectInputStream.read(any(byte[].class))).thenAnswer(invocation -> {
return testInputStream.read(invocation.getArgument(0));
});
我有一个更广泛的例子。希望有帮助。您可以使用Mockito的答案来模拟流
String expectedContents = "Some contents";
InputStream testInputStream = new StringInputStream(expectedContents);
S3ObjectInputStream s3ObjectInputStream = mock(S3ObjectInputStream.class);
S3Object s3Object = mock(S3Object.class);
AmazonS3Client amazonS3Client = mock(AmazonS3Client.class);
S3AttachmentsService service = new S3AttachmentsService(amazonS3Client);
when(s3ObjectInputStream.read(any(byte[].class))).thenAnswer(invocation -> {
return testInputStream.read(invocation.getArgument(0));
});
我有一个更广泛的例子。希望能有所帮助。正是我想要的!这正是我要找的!