如何将单元测试上传目录写入S3?
How to write unit test upload directory to S3?
我有一个方法可以将目录上传到 s3。
我想为它编写一个单元测试并且我一直在搜索,但大多数测试都是集成测试。
也许我不应该为这种过程做单元测试?
我没有使用 testcontainers 进行集成测试的权限,所以我不能使用 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) {
... do something here
} finally {
transferManager.shutdownNow();
}
}
似乎方法中没有太多单元测试,只有参数和交互。
模拟 TransferManager
并不是真正的解决方案,因为您需要模拟 MultipleFileUpload
,并且还需要添加调用 ProgressListener
的代码。你最终会嘲笑一切让它变得无用的东西。测试一个广泛使用的库对你也没有太大的价值。
我会测试在集成测试期间不太可能发生(又名不可重复)的异常情况。
大致是这样的(假设 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()
);
我有一个方法可以将目录上传到 s3。 我想为它编写一个单元测试并且我一直在搜索,但大多数测试都是集成测试。 也许我不应该为这种过程做单元测试? 我没有使用 testcontainers 进行集成测试的权限,所以我不能使用 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) {
... do something here
} finally {
transferManager.shutdownNow();
}
}
似乎方法中没有太多单元测试,只有参数和交互。
模拟 TransferManager
并不是真正的解决方案,因为您需要模拟 MultipleFileUpload
,并且还需要添加调用 ProgressListener
的代码。你最终会嘲笑一切让它变得无用的东西。测试一个广泛使用的库对你也没有太大的价值。
我会测试在集成测试期间不太可能发生(又名不可重复)的异常情况。
大致是这样的(假设 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()
);