junit和Mockito单位测试for Stream.mark(stream.abable)执行S3 PutObject时

发布于 2025-01-31 07:47:11 字数 1606 浏览 1 评论 0 原文

我有一种将InputStream放入S3存储桶中的方法。

@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);
    }

我想使方法引起ioexception,然后投掷Runtime Exception,然后为此编写了单位测试。

@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));
    }

这是我尝试的方法,但是这显示了编辑器中的错误,

Required type:
T
Provided:
void
reason: no instance(s) of type variable(s) T exist so that void conforms to T

该如何使方法投掷ioexception?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

木有鱼丸 2025-02-07 07:47:11

stream.mark(...) will 永远不要抛出任何检查过的例外无论如何,这是毫无意义的。

您也无需手动标记或重置流。 SDK执行背后场景

默认情况下, java尝试的AWS SDK 通过标记在转移开始之前的输入流,然后重置 >在重试之前。

如果您的流大于128 kb,则您可能需要调用 setReadLimit 至1个字节大于流的大小,以避免使用 resetexception 当不使用 > fileInputStream 。如果不是,那么您无需做任何事情。无论如何,您不需要自己标记或重置流。

但是,出于参考目的, Mockito。(...)。Thenthrow(...)用于返回值的方法调用。

stream.mark(apcstream.available())是一种方法调用, not 返回值(void return类型)。

::

使用 dothrow()当您想用异常使用void方法时。

在这种情况下,替换

Mockito.when(mockStream.mark(mockStream.available())).thenThrow(IOException.class);

为:

doThrow(IOException.class).when(mockStream).mark(mockStream.available());

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());
时光与爱终年不遇 2025-02-07 07:47:11

bytearrayInputStream 。当 mark 。文档清楚地指出,可以抛出 ioexception ,并且该参数被忽略。

异常不是来自标记调用,它来自可用调用。由于参数被忽略,只需将其替换为0,就无需捕获 ioexception 。实际上,您会收到一个编译器错误:

例外Java.io.io.ioexception永远不会扔在相应的试验语句

的主体中

stream is a ByteArrayInputStream. That will never ever ever throw any exception when mark is called. The documentation clearly states that no IOException can be thrown, and that the argument is ignored.

The exception doesn't come from the mark call, it comes from the available call. As the argument is ignored, just replace it with 0, and you don't need to catch the IOException. In fact, you'll get a compiler error:

exception java.io.IOException is never thrown in body of corresponding try statement

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文