英文:
How to write unit test upload directory to S3?
问题
我有一个将目录上传到S3的方法。
我想为它编写一个单元测试,我一直在搜索,但大多数测试都是集成测试。
也许我不应该为这种类型的流程编写单元测试?
我没有使用集成测试的特权,所以无法使用testcontainers。
以下是我的代码:
public void uploadDir(final Path path, final String key) throws InternalServerError {
final TransferManager transferManager = TransferManagerBuilder.standard()
.withS3Client(s3Client)
.build();
final ProgressListener progressListener = progressEvent -> {
if (progressEvent.getBytesTransferred() > 0) {
double percentTransferred = progressEvent.getBytesTransferred() * 100.0 / progressEvent.getBytes();
log.info("Transferred " + percentTransferred + "%");
}
};
final MultipleFileUpload xfer = transferManager.uploadDirectory("mybucket", key, path.toFile(), true);
xfer.addProgressListener(progressListener);
xfer.waitForCompletion();
log.info("Upload has been completed.");
} catch (final AmazonServiceException | InterruptedException exception) {
... 在此处执行某些操作
} finally {
transferManager.shutdownNow();
}
}
英文:
I have a method to upload directory to s3.
I would like to write a unit test for it and I've been searching, but most test are integration tests.
Maybe I'm not supposed to do a unit test for this kind of process?
I don't have a privileges to use testcontainers for integration test, so I can’t use testcontainers.
Here is my code
public void uploadDir(final Path path, final String key) throws InternalServerError {
final TransferManager transferManager = TransferManagerBuilder.standard()
.withS3Client(s3Client)
.build();
final ProgressListener progressListener = progressEvent -> {
if (progressEvent.getBytesTransferred() > 0) {
double percentTransferred = progressEvent.getBytesTransferred() * 100.0 / progressEvent.getBytes();
log.info("Transferred " + percentTransferred + "%");
}
};
final MultipleFileUpload xfer = transferManager.uploadDirectory("mybucket", key, path.toFile(), true);
xfer.addProgressListener(progressListener);
xfer.waitForCompletion();
log.info("Upload has been completed.");
} catch (final AmazonServiceException | InterruptedException exception) {
... do something here
} finally {
transferManager.shutdownNow();
}
}
答案1
得分: 2
以下是翻译好的内容:
似乎方法中没有太多单元测试的内容,只涉及参数和交互。
模拟TransferManager
并不是一个真正的解决方案,因为你需要模拟MultipleFileUpload
,而且调用ProgressListener
的代码也需要添加。最终你会模拟所有东西,这使得单元测试失去了意义。对于一个广泛使用的库进行测试对你来说也没有太多价值。
我会测试异常情况,这是在集成测试中不太可能发生的情况(即不可重复的)。大致上是这样的(假设使用Mockito):
@Test
void uploadDirFailsTest() {
TransferManager mockTM = mock(TransferManager.class);
doThrow(new AmazonServiceException(...)) // 希望它有一个公共构造函数
.when(mockTM)
.uploadDirectory(eq("mybucket"), any(), any(), eq(true)); // 如果需要更多匹配的话
YourClassName instance = new YourClassName(mockTM);
instance.uploadDir(path, key);
/*
在这里验证正确的异常处理,或者如果重新抛出异常,则在调用周围包装为 assertThrows()
*/
}
public class YourClassName {
final TransferManager transferManager;
public YourClassName(TransferManager transferManager) {
this.transferManager = transferManager;
}
public void uploadDir(final Path path, final String key) throws InternalServerError {
final ProgressListener progressListener = progressEvent -> {
if (progressEvent.getBytesTransferred() > 0) {
double percentTransferred = progressEvent.getBytesTransferred() * 100.0 / progressEvent.getBytes();
log.info("已传输 " + percentTransferred + "%");
}
};
final MultipleFileUpload xfer = transferManager.uploadDirectory("mybucket", key, path.toFile(), true);
xfer.addProgressListener(progressListener);
xfer.waitForCompletion();
log.info("上传已完成。");
} catch (final AmazonServiceException | InterruptedException exception) {
... 在这里进行处理
} finally {
transferManager.shutdownNow();
}
}
// 实际使用
new YourClassName(
TransferManagerBuilder.standard()
.withS3Client(s3Client)
.build()
);
英文:
It seems there's not much to unit test in the method but arguments and interactions.
Mocking TransferManager
isn't really a solution because you'd need to mock MultipleFileUpload
, and also the code that calls ProgressListener
needs to be added. You'd end up mocking everything which makes it useless. Testing a widely used library also has not much value for you.
I'd test the exception case which is an unlikely case to happen (aka not repeatable) during integration testing.
Roughly something like this (assuming mockito):
@Test
void uploadDirFailsTest() {
TransferManager mockTM = mock(TransferManager.class);
doThrow(new AmazonServiceException(...)) // hopefully it has a public constructor
.when(mockTM)
.uploadDirectory(eq("mybucket"), any(), any(), eq(true)); //more matching if needed
YourClassName instance = new YourClassName(mockTM);
instance.uploadDir(path, key);
/*
verify correct exception handling here or
if you rethrow the exception wrap the call with
assertThrows()
*/
}
public class YourClassName {
final TransferManager transferManager;
public YourClassName(TransferManager transferManager) {
this.transferManager = transferManager;
}
public void uploadDir(final Path path, final String key) throws InternalServerError {
final ProgressListener progressListener = progressEvent -> {
if (progressEvent.getBytesTransferred() > 0) {
double percentTransferred = progressEvent.getBytesTransferred() * 100.0 / progressEvent.getBytes();
log.info("Transferred " + percentTransferred + "%");
}
};
final MultipleFileUpload xfer = transferManager.uploadDirectory("mybucket", key, path.toFile(), true);
xfer.addProgressListener(progressListener);
xfer.waitForCompletion();
log.info("Upload has been completed.");
} catch (final AmazonServiceException | InterruptedException exception) {
... do something here
} finally {
transferManager.shutdownNow();
}
}
//real use
new YourClassName(
TransferManagerBuilder.standard()
.withS3Client(s3Client)
.build()
);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论