shl*_*chz 3 c# unit-testing moq mocking azure-storage-blobs
我有一个名为A的项目,它有一个名为ClassA的类. ClassA有一个名为ReadBlock()的方法,它创建一个CloudBlockBlob对象并调用其中一个方法.
CloudBlockBlob是一个位于Microsoft.WindowsAzure.Szrage.Blob命名空间的类,该命名空间位于Microsoft.WindowsAzure.Storage.dll中.
我的项目A有一个名为A.Tests的单元测试项目.现在,我想测试方法ReadBlock().为了测试它,我需要模拟CloudBlockBlob对象并拦截对其方法的调用,返回自定义值并验证方法是否被调用.
更新: 问题是我是否可以在不修改项目A的代码的情况下完成此操作.
谢谢!
如果不修改类A代码,您将无法ReadBlock使用Moq 来修改该方法.您将能够使用代码编织工具(MsFakes,Typemock隔离器等)来使用此方法.
例如(MsFakes):
[TestMethod]
public void TestMethod1()
{
using (ShimsContext.Create())
{
ShimCloudBlockBlob.AllInstances.<the method you want to override> = (<the method arguments>) => {};
}
}
Run Code Online (Sandbox Code Playgroud)
在using范围内,您将能够通过属性覆盖CloudBlockBlob具有的任何方法AllInstances.
在下一节中,我将讨论您拥有的所有其他选项......
选项1:
public class A
{
private IBlockBlob _blockBlob;
public A(IBlockBlob blockBlob)
{
_blockBlob = blockBlob;
}
public void ReadBlock()
{
_blockBlob.DoSomething();
}
}
Run Code Online (Sandbox Code Playgroud)
由于您每次调用时创建一个新实例ReadBlock(您的方法的当前行为),您最好注入工厂而不是包装器,DoSomething应该是create; 选项2:
public class A
{
private readonly IFactoryBlockBlob _blobFctory;
public A(IFactoryBlockBlob blobFctory)
{
_blobFctory = blobFctory;
}
public void ReadBlock()
{
var blob = _blobFctory.Create();
}
}
Run Code Online (Sandbox Code Playgroud)
但是,根据您的问题和您的评论,您的班级似乎"有依赖"而不是"需要依赖".
(马克西门子写了一本关于DI的好书,这张图取自他的书)
有了这条新信息,您的方法应该是这样的; 选项3:
public class A
{
public void ReadBlock(ICloudBlob blob)
{
}
}
Run Code Online (Sandbox Code Playgroud)
但是你不想改变方法的签名:
public class A
{
public void ReadBlock()
{
ReadBlock(new CloudBlockBlob(<the params bla bla...>));
}
internal void ReadBlock(ICloudBlob blob)
{
}
}
Run Code Online (Sandbox Code Playgroud)
单击添加InternalsVisibleToAttribute,然后验证内部方法的行为.
通过阅读这些内容,我觉得您的课程是一种"遗留代码",意味着它可以完成工作,不会改变,并且验证其行为可能是浪费时间.在过去,我发布了一个图表(在这个答案中),可以帮助您决定处理此案例的方法.