c# - 如何从 amazon s3 模拟/单元测试下载?
问题描述
我是单元测试/起订量的新手,想知道如何做到这一点。我有一个将文件从 s3 下载到本地的功能。我如何模拟它,使其实际上不使用 transferUtility 从 s3 下载任何内容?
bool downloadFileFromS3(string localPathToSave, string filenameToDownloadAs, string bucketName, string objectKey)
{
try
{
string accessKey = "xxx";
string secretKey = "xxx";
// do stuff before
TransferUtility transferUtility = new TransferUtility(accessKey, secretKey);
transferUtility.Download( Path.Combine(localPathToSave, filenameToDownloadAs), bucketName, objectKey );
// do stuff after
return true;
}
catch (Exception e)
{
// stuff
}
}
我已经创建了模拟,但我不知道如何使用它来测试我编写的函数。
[Test]
public void testDownloadFromS3()
{
string filePath = null;
string bucketName = null;
string key = null;
Mock<Amazon.S3.Transfer.TransferUtility> mock = new Mock<Amazon.S3.Transfer.TransferUtility>();
//mock.Setup(x => x.Download(filePath, bucketName, key)).Verifiable();
//Mock.Verify();
}
解决方案
根据文档,TransferUtility
该类实现了ITransferUtility
接口。
如果您需要测试您的代码,downloadFileFromS3
那么您的代码应该依赖于抽象,而不是像SOLID 的 DIP所说的那样依赖于具体。
private readonly ITransferUtility transferUtility; //should be set via constructor injection
bool downloadFileFromS3(string localPathToSave, string filenameToDownloadAs, string bucketName, string objectKey)
{
try
{
// do stuff before
transferUtility.Download( Path.Combine(localPathToSave, filenameToDownloadAs), bucketName, objectKey );
// do stuff after
return true;
}
catch (Exception e)
{
// stuff
}
}
因为该Download
方法不返回任何内容,所以您需要做的就是设置可验证性以防万一
[Test]
public void testDownloadFromS3_HappyPath()
{
//Arrange
const string localPathToSave = "C:/tmp/";
const string filenameToDownloadAs = "test.txt";
const string bucketName = "x";
const string objectKey = "y";
Mock<Amazon.S3.Transfer.ITransferUtility> transferUtilMock = new Mock<Amazon.S3.Transfer.ITransferUtility>();
transferUtilMock
.Setup(util => util.Download(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()))
.Verifiable();
var sut = new ClassThatContainsTheDownloadFileFromS3(transferUtilMock.Object);
//Act
var result = sut.downloadFileFromS3(localPathToSave, filenameToDownloadAs, bucketName, objectKey);
//Assert
Assert.IsTrue(result);
transferUtilMock.Verify(util => util.Download(
It.Is<string>(filePath => string.Equals(filePath, localPathToSave +filenameToDownloadAs, StringComparison.InvariantCultureIgnoreCase)),
It.Is<string>(bucket => string.Equals(bucket, bucketName, StringComparison.InvariantCultureIgnoreCase)),
It.Is<string>(key => string.Equals(key, objectKey, StringComparison.InvariantCultureIgnoreCase)),
Times.Once);
}
- 我们已设置模拟以接受任何参数(It.IsAny)
- 我们已将模拟实例的
Object
属性传递给包含downloadFileFromS3
- 我使用了一个名称 sut,它指的是System Under Test
- 我们已经使用It.Is来验证该
Download
方法是否以我们期望的方式被调用 - 我们还将a传递
Times.Once
给 theVerify
以确保Download
已准确调用了一次。
这是您可以测试不愉快路径的方法:
[Test]
public void testDownloadFromS3_UnhappyPath()
{
//Arrange
const string localPathToSave = "C:/tmp/";
const string filenameToDownloadAs = "test.txt";
const string bucketName = "x";
const string objectKey = "y";
Mock<Amazon.S3.Transfer.ITransferUtility> transferUtilMock = new Mock<Amazon.S3.Transfer.ITransferUtility>();
transferUtilMock
.Setup(util => util.Download(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>()))
.Throws<System.IO.IOException>();;
var sut = new ClassThatContainsTheDownloadFileFromS3(transferUtilMock.Object);
//Act
var result = sut.downloadFileFromS3(localPathToSave, filenameToDownloadAs, bucketName, objectKey);
//Assert
Assert.IsFalse(result);
transferUtilMock.Verify(util => util.Download(
It.Is<string>(filePath => string.Equals(filePath, localPathToSave +filenameToDownloadAs, StringComparison.InvariantCultureIgnoreCase)),
It.Is<string>(bucket => string.Equals(bucket, bucketName, StringComparison.InvariantCultureIgnoreCase)),
It.Is<string>(key => string.Equals(key, objectKey, StringComparison.InvariantCultureIgnoreCase)),
Times.Once);
}
- 如您所见,我们已将调用替换为在
Verifiable
调用时Throws
抛出异常 - 我也更换了
Assert.IsTrue
toAssert.IsFalse
- 我假设在异常
// stuff
返回的情况下false
- 我假设在异常
推荐阅读
- sql - 编辑插入的表 sql
- c# - 使用 Bot Framework Composer 2 和 C# 运行时创建的机器人中的 TurnState 是什么?
- python - 解析 JSON 以存储在 SQL 数据库中的最佳方法(SQL 存储过程/Python)
- video - 如何在使用 libav 将视频混合到 mp4 容器时补偿帧速率不足
- python - 使用 Pandas_profiling 汇总数据时出错
- d3.js - 从 v3 更新 D3 缩放行为
- mongodb - Mongo/Express/Node 连接问题,API 路由失败
- c++ - C++ 可重新赋值的 const 成员变量
- html - 如何通过点击传递价值?
- roblox - Roblox Pathfinding 到达目的地时的来回移动需要跳跃