如何在存在依赖性时设计可模拟性?

时间:2013-03-28 16:49:30

标签: c# asp.net unit-testing mocking tdd

我有一个方法,它调用.NET XDocument.Load()方法从URL加载xml数据。我想让我的班级单元可以测试。

那么如何使该调用可模拟/单元可测试?

private void ProcessData(string url)
{
            // todo: make this mockable
            var xDocument = XDocument.Load(url);
            // the rest of the code
}

我使用的一个解决方案是将xmlUrlLoader注入到clas中,如下所示:

private readonly Func<string, XDocument> _xmlUrlLoader;

public MyConstructor(Func<string,XDocument> xmlUrlLoader)
{
    _xmlUrlLoader = xmlUrlLoader;
}
private void ProcessData(string url)
{
            // todo: make this mockable
            var xDocument = this._xmlUrlLoader(url);
            // the rest of the code
}

还有更好的方法吗?

2 个答案:

答案 0 :(得分:3)

我同意注入一个加载器是正确的方法我不知道为什么它会是Func类型

我希望界面符合

的界限
public interface IXmlDocumentLoader
{
    XDocument LoadDocument(string url);
}

然后你的代码看起来像

private readonly IXmlDocumentLoader _xmlUrlLoader;

public MyConstructor(IXmlDocumentLoader xmlUrlLoader)
{
    _xmlUrlLoader = xmlUrlLoader;
}

private void ProcessData(string url)
{
            var xDocument = this._xmlUrlLoader(url);
            // the rest of the code
}

但我认为,出于分离关注的原因,文档加载器肯定应该属于自己的类。

答案 1 :(得分:3)

我更喜欢将逻辑与访问资源分开。在您的情况下,我将文档传递给处理函数:

void ProcessData(XDocument xDocument);

您可以在不嘲笑任何内容的情况下测试该功能。然后,如果您愿意,可以在顶部添加一个薄的包装来进行加载。

void ProcessUrl(string url);
{
    var xDocument = XDocument.Load(url);
    ProcessData(xDocument);
}

你可以使用模拟来对包装器进行单元测试,但我个人并没有从中看到很多好处。我更喜欢仅在集成测试中使用这些包装器。