我正在尝试为我创建的一个新项目编写单元测试,并且我遇到了一个问题,我无法弄清楚我打算编写的类是如何实际可测试的。下面我简化了我想写的课程,让你了解我想要实现的目标。
所以我有一个XML解析器,它只需从给定的URL访问XML文件,提取我需要的数据并将其作为对象返回。所以我的代码看起来像这样(验证和人口尚未完成,但你明白了):
public UserDetails ParseUserDetails(string request, string username, string password)
{
var response = new XmlDocument();
response.Load(string.Format(request + "?user={0}&password={1}", username, password));
// Validation checks
return new UserDetails { // Populate object with XML nodes };
}
目前我的班级不可测试。我无法模拟加载以抛出WebException以查看我的类如何处理错误,并且在我通过有效的URL之前,当我针对此类运行测试时,它总是会抛出异常。我也无法测试从类中返回的数据,因为我无法模拟XML文档,因为它是从另一个URL加载的。
我可以把它拆分成一个可模拟的对象,从URL中检索XML并将其命名为IXmlDocumentLoader,但后来我遇到了同样的问题,我有这样的类:
public class XmlDocumentLoader : IXmlDocumentLoader
{
public XmlDocument LoadXmlDocument(string request, string username, string password)
{
var response = new XmlDocument();
response.Load(string.Format(request + "?user={0}&password={1}", username, password));
return response;
}
}
这将使ParseUserDetails方法更易于测试,但现在类XmlDocumentLoader不可测试。我刚刚把问题转移到其他地方了吗?我的问题是,所有课程都必须是可测试的,还是我误解了单元测试?
答案 0 :(得分:4)
这肯定是一个"意见"问题,因此,可能会被关闭。
但我会给你一个建议。
拆分一切。使用&#34的原则;一个对象应该只做一件事"。下载文件是一回事,验证它是另一回事。如果你同时选择两者,你可以测试它们。
您可以在通用文件上测试下载系统(不必是生产站点),并测试系统是否正常工作。你可以提供一个假文件"测试验证,也不必是生产文件。
这两项测试都可以让您了解代码的运行情况。
答案 1 :(得分:2)
XmlDocument.Load(string filename) documentation in MSDN因此定义filename
参数:
filename :包含要加载的XML文档的文件的URL。 URL可以是本地文件或HTTP URL(Web地址)。
(强调我的)
因此,如果您的ParseUserDetails
测试通过file://C:/path/to/my/test/file
作为request
参数传递,那么您的代码完全可以测试。他们可能看起来像这样:
public void SomeRandomTest()
{
string testFileLocalPath = @"C:\path\to\my\test\file";
// Code to create an XML file with expected data goes here ...
UriBuilder ub = new UriBuilder();
ub.Scheme = "file";
ub.Host = "";
ub.Path = testFileLocalPath;
string request = ub.ToString();
var target = new SomethingThatReadsXml();
var details = target.ParseUserDetails(request, "dummy", "whocares");
// Compare returned user details to expected values here ...
}
答案 2 :(得分:1)
这个问题并不容易,我不同意这个代码应该用于工作而不需要测试的意见。我个人会做集成测试,测试你可以在构建过程中运行的实际现实情况。
为了使LOGIC可测试,我会将这个东西分开(就像你提到的那样)并让你的Parser使用Stream(或等同物)。基于Streams的IO-Code的优点是,您可以使用MemoryStreams伪造数据,因此您可以通过测试中编写的XML代码测试您的Parser。要测试从Web检索XML并将其作为Stream返回的另一件事,模拟会有点复杂,但逻辑应该更容易,您只需要测试输入和一些无效URL /凭证的集成测试/ ......实际的检索实际上是.Net实现(你不必测试)。
最后,你将达到一个你不能伪造的外部边界,但是xml解析器不应该是那个;)
在这里你可以看到一个例子: VS Magazine