【发布时间】:2018-02-03 04:30:22
【问题描述】:
我正在尝试为我的 AzureBlobRepository 编写单元测试。存储库在构造函数中接收 CloubBlobClient。我想模拟客户端,但这给出了一个例外:
using (var mock = AutoMock.GetLoose())
{
var mockClient = mock.Mock<CloudBlobClient>();
}
无法在类型“Microsoft.WindowsAzure.Storage.Blob.CloudBlobClient”上的多个长度为 2 的构造函数之间进行选择。注册组件时,使用 UsingConstructor() 配置方法显式选择构造函数。
当然,在我的单元测试中我没有注册任何东西,所以该消息不是很有帮助。
我还尝试了其他方法,例如提供 NameParameters、TypedParameters 或调用 mock.Create 代替 mock.Mock,但我尝试的所有方法都返回相同的异常消息。
(同样的问题也出现在 CloudBlobContainer 上)
实现接口后更新 这是我编写的单元测试示例:
[TestMethod]
public void AzureBlobRepository_GetByIdAsync_ReturnsContent()
{
Guid blobId = Guid.NewGuid();
Guid directoryName = Guid.NewGuid();
string containerName = "unittest";
using (var mock = AutoMock.GetLoose())
{
var mockClient = mock.Mock<ICloudBlobClient>();
var mockContainer = mock.Mock<ICloudBlobContainer>();
var mockDirectory = mock.Mock<ICloudBlobDirectory>();
// notice that we're not using AutoMock here, it fails to create the mock
var mockBlob = new Mock<CloudBlockBlob>(new Uri($"http://tempuri.org/{containerName}/{directoryName}/{blobId}"));
mockBlob.Setup(m => m.DownloadTextAsync()).Returns(Task.FromResult("content"));
mockClient.Setup(m => m.GetContainerReference(containerName))
.Returns(mockContainer.Object);
mockContainer.Setup(m => m.GetDirectoryReference(directoryName.ToString()))
.Returns(mockDirectory.Object);
mockDirectory.Setup(m => m.GetBlockBlobReference(blobId.ToString()))
.Returns(mockBlob.Object);
var repository = mock.Create<AzureBlobRepository>(
new TypedParameter(typeof(ICloudBlobClient), mockClient.Object),
new NamedParameter("container", containerName),
new NamedParameter("directory", directoryName));
var result = repository.GetByIdAsync(blobId, directoryName).Result;
result.ShouldBe("content");
}
}
【问题讨论】:
-
这些类应被视为第 3 方实施问题。这意味着您无法控制它们,我们不应该嘲笑我们无法控制的东西。它们应该封装在您可以控制的抽象后面,并且可以在单独测试时根据需要进行模拟。由于这个原因,类应该依赖于抽象而不是具体。模拟具体类往往会产生连锁反应
-
这些类已在 Azure 存储 SDK 的最新更新中进行了修改(虚拟化方法),用于单元测试。
-
好吧,我不知道。文档尚未更新以反映该更改。
-
我相信Provide可以工作。在这种情况下,它只是被错误地使用了。看docs.autofac.org/en/latest/integration/…
-
@Nkosi 也许你对添加抽象层的看法是正确的。在我的情况下,我可以随意设置 CloudBlobClient 和 CloudBlobContainer,但是我也必须使用 CloudBlobDirectory,它没有公共构造函数,因此不能由 Moq 创建..
标签: c# unit-testing moq autofac azure-blob-storage