Issue
I have a method which puts InputStream in s3 bucket.
@Override
public String putObject(@NonNull String s3BucketName, @NonNull String s3Key, @NonNull String content,
@NonNull ObjectMetadata metadataRequest) {
InputStream stream = new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8));
try {
stream.mark(stream.available());
} catch (IOException e) {
String errorMessage = String.format("Runtime error while marking stream.",
s3BucketName, s3Key);
throw new RuntimeException(errorMessage, e);
}
PutObjectRequest request = new PutObjectRequest(s3BucketName, s3Key, stream, metadataRequest);
return putObject(request);
}
I want to make the method cause IOException and then throw RuntimeException and I have written the unit test for the same.
@Test
public void putObjectTest_withStringContent_withMetadataRequest_IOError() {
ObjectMetadata metadataRequest = new ObjectMetadata();
metadataRequest.addUserMetadata(TEST_METADATA_KEY, TEST_METADATA_VALUE);
InputStream mockStream = Mockito.mock(InputStream.class);
Mockito.when(mockStream.mark(mockStream.available())).thenThrow(IOException.class);
assertThrows(RuntimeException.class, () -> s3Accessor.putObject
(TEST_S3BUCKET, TEST_S3OBJECT, TEST_STRING, metadataRequest));
}
This is what I have tried but this is showing error in editor
Required type:
T
Provided:
void
reason: no instance(s) of type variable(s) T exist so that void conforms to T
How can I make the method throw IOException?
Solution
stream.mark(...)
will never throw any checked exceptions anyway so this is rather pointless.
You also don't need to mark or reset the stream manually at all. The SDK does that behind the scenes.
By default, the AWS SDK for Java attempts to retry failed transfers by marking the input stream before the start of a transfer and then resetting it before retrying.
If your stream is larger than 128 KB, then you may need to call setReadLimit
to 1 byte greater than the size of the stream to avoid a ResetException
when not using a FileInputStream
. If it isn't, then you don't need to do anything. Regardless, you don't need to mark or reset the stream yourself.
However, for reference purposes, Mockito.when(...).thenThrow(...)
is for method invocations that return a value.
stream.mark(mockStream.available())
is a method invocation that does not return a value (void return type).
As per docs:
Use doThrow() when you want to stub the void method with an exception.
In this case, replace:
Mockito.when(mockStream.mark(mockStream.available())).thenThrow(IOException.class);
With:
doThrow(IOException.class).when(mockStream).mark(mockStream.available());
Answered By - Ermiya Eskandary
Answer Checked By - Katrina (JavaFixing Volunteer)