我正在尝试使用Moq从LLBLGen的 IDataAccessAdapter 接口模拟扩展方法。这是 FetchQueryAsync 扩展方法。
这样做给了我我无法模拟静态扩展方法的错误。但是没有办法我可以更改代码。因此,我尝试创建包装器类,但由于不知道如何应用它,因此我也没有成功。
在Fetch方法中,我希望FetchQueryAsync返回测试期间指定的对象,而不实际执行查询。
public class QueryHandler
{
private IDataAccessAdapterProvider dataAccessAdapterProvider;
public QueryHandler(IDataAccessAdapterProvider provider)
{
this.dataAccessAdapterProvider = provider;
}
private async Task<T> Fetch(DynamicQuery<T> query)
{
using (IDataAccessAdapter adapter = dataAccessAdapterProvider.Provide()
{
result = await adapter.FetchQueryAsync(query)
}
}
}
public class DataAccessAdapterProvider : IDataAccessAdapterProvider
{
public IDataAccessAdapter Provide()
{
var adapter = new DataAccessAdapter();
return adapter;
}
}
所以在我的单元测试中,我有这个:
List<int> il = new List<int>();
Mock<IDataAccessAdapterProvider> mock = new Mock<IDataAccessAdapterProvider>();
mock.Setup(m => m.Provide()
.FetchQueryAsync<int>(It.IsAny<DynamicQuery<int>>()))
.ReturnsAsync(il);
但是这不起作用,因为它不受支持。 所以我尝试将这种方法包装起来。
interface IWrap
{
Task<List<TElement>> FetchQueryAsync<TElement>(IDataAccessAdapter adapter, DynamicQuery<TElement> query);
}
public class Wrap : IWrap
{
public async Task<List<TElement>> FetchQueryAsync<TElement>(IDataAccessAdapter adapter, DynamicQuery<TElement> query)
{
return await adapter.FetchQueryAsync(query);
}
}
如何使用带有Moq的包装器来模拟界面?
答案 0 :(得分:2)
您从扩展方法开始,然后创建了IWrap
接口以及使用该扩展方法的实现。太完美了。
现在您所需要做的就是将其注入您的类中,就像已经注入IDataAccessAdapterProvider
一样:
public class QueryHandler
{
private readonly IDataAccessAdapterProvider _dataAccessAdapterProvider;
private readonly IWrap _wrap; //I'm assuming you'll want a different name.
public QueryHandler(IDataAccessAdapterProvider provider, IWrap wrap)
{
_dataAccessAdapterProvider = provider;
_wrap = wrap;
}
(我在那儿应用了一个通用约定。在字段名前加下划线-_wrap
-表示字段和构造函数参数具有不同的名称,因此您无需指定this.wrap
。另外,当人们在其他地方看到下划线时,他们会知道这是一个字段。)
现在您可以模拟界面:
var mock = new Mock<IWrap>();
var returnedFromMock = new List<int> { 1, 2, 3 };
mock.Setup(x => x.FetchQueryAsync<int>(It.IsAny<IDataAccessAdapter>(), It.IsAny<DynamicQuery<int>>()))
.ReturnsAsync(returnedFromMock);
您提到无法更改代码。我不确定您不能更改哪个部分,但是如果您不能更改QueryHandler
来替换其具体的依赖项,那么这可能只是关于静态依赖项的警告。
不过,您有源代码。如果您不能更改现有的类,则可以仅根据现有的源代码创建一个新的类。如果有人问为什么您要复制现有的类,只需(以句法)说您不想复制代码-您宁可修复现有的类以使其可测试。