C# 如何对需要显示特定文件的类进行单元测试
我目前正在努力学习正确的单元测试。因此,现在我尝试为一个类编写单元测试,该类应该将数据从XML文件映射到适当的对象。当然,该类的所有功能都依赖于相应XML文件的存在。XML文件加载到类的构造函数中 我在用C#和NUnit。到目前为止,我有两个测试:C# 如何对需要显示特定文件的类进行单元测试,c#,unit-testing,nunit,C#,Unit Testing,Nunit,我目前正在努力学习正确的单元测试。因此,现在我尝试为一个类编写单元测试,该类应该将数据从XML文件映射到适当的对象。当然,该类的所有功能都依赖于相应XML文件的存在。XML文件加载到类的构造函数中 我在用C#和NUnit。到目前为止,我有两个测试: [Test] public void ShouldAllowInstanceToBeCreatedWhenXMLFileIsPresent() { if (File.Exists(SettingsReader.XML_SETTINGS_PAT
[Test]
public void ShouldAllowInstanceToBeCreatedWhenXMLFileIsPresent()
{
if (File.Exists(SettingsReader.XML_SETTINGS_PATH))
{
SettingsReader settingsReader = new SettingsReader();
Assert.AreNotEqual(null, settingsReader);
}
}
[Test]
[ExpectedException("Telekanzlei.Clientmanager.XMLDataLayer.XMLFileNotFoundException")]
public void ShouldThrowExceptionWhenXMLFileIsNotPresent()
{
if (!File.Exists(SettingsReader.XML_SETTINGS_PATH))
{
SettingsReader settingsReader = new SettingsReader();
}
else
throw new XMLFileNotFoundException();
}
我不确定在测试中检查文件的存在是否是一种正确的方法,因此欢迎对这些测试提出任何建议。但我的问题是,如何进行以下测试。显然,如果XML文件不存在,下面的所有测试都将失败
那么,我是否假设XML文件存在,同时记住,测试失败可能意味着它不存在?那对我来说似乎不合适
有没有一个通用的模式来处理这样的问题
谢谢你的帮助
编辑:重写第二个测试,因为如果该文件实际存在,则该测试将失败
编辑2:也许这有助于告诉你,设置阅读器实际上是做什么的。目前看来是这样的:
public class SettingsReader
{
public static readonly string XML_SETTINGS_PATH = "C:\\Telekanzlei\\Clientmanager_2.0\\Settings.xml";
public XElement RootXElement { get; private set; }
public SettingsReader()
{
if (!File.Exists(XML_SETTINGS_PATH))
throw new XMLFileNotFoundException();
using (var fs = File.OpenRead(XML_SETTINGS_PATH))
{
RootXElement = XElement.Load(fs);
}
}
}
我不确定,但我想StreamReader不适合这里,是吗?如果必须,我建议您使用安装方法复制或验证文件是否存在。 我建议将该文件添加到测试项目中,并将其标记为“始终复制”,以确保该文件存在。一旦该文件开始工作,则无需重新检查。
如果您有许多需要外部文件的测试,也许您应该使用MsTest-它有一个名为DeploymentItem的属性,确保将文件复制到与测试相同的位置。考虑重写代码,以便可以传入依赖项,或者以某种方式为要进行单元测试的代码设置存根
例如,将类似“IMySettingsFileProvider”的实例传递给SettingsReader构造函数,其中IMySettingsFileProvider.SettingsXml返回一些设置流。通过这种方式,您可以为测试模拟IMySettingsFileProvider接口,而不需要在磁盘上显示文件。问题不在于单元测试,而在于类的设计。我建议重构该类,使其不打开文件,而是在流上操作。然后,您的单元测试可以简单地将文件流替换为内存流-simples!:)
公共类设置阅读器()
{
公共设置读卡器(System.IO.StreamReader读卡器)
{
//读取流的内容。。。
}
}
//在生产代码中:
新的设置阅读器(新的StreamReader(File.Open(“settings.xml”));
//单元测试中:
新设置阅读器(新StringReader(“虚拟设置”);
请记住,打开文件和解析设置数据是两个截然不同的问题。一个选项是将其放在测试夹具的顶部。那么测试只有在文件存在时才有效
[SetUp]
public void Setup()
{
Assume.That(File.Exists(SettingsReader.XML_SETTINGS_PATH));
}
SettingsReader是否设计为使用依赖项注入?听起来是DI的一个很好的例子,mocking.MSTest有[DeploymentItem]用于此。也许NUnit有类似的东西?这不是有点“过火”吗?XML文件仅由这个类使用。仅为加载文件而创建接口+类?同意。我不明白为什么人们会因为嘲笑是“纯粹”的方式而增加这么多的复杂性。你最好利用创建文件的代码来创建它/将它复制到临时位置,使用它,然后删除它。是的,它可能是。这就是为什么我试着写“考虑…”——如果它对您的案例有效,那么就这样做,如果没有,那么就做其他事情(这已经被建议作为早期的答案)。我刚刚意识到XElement.Load-method将流作为参数。我还不太熟悉.NET。但你的建议似乎是个好办法。所以我将把它拆分成一个SettingsStreamProvider类和一个SettingsParser类,并对解析器使用依赖注入?一个setting stream provider类对一个普通流有什么价值?我认为这将是一个毫无意义的抽象-KISS:)要点^^问题是我在项目中多次使用SettingsReader,但总是使用同一个XML文件。我不太喜欢每次使用时“手动”创建一个新流。这就是为什么我想在SettingsReader类中首先处理流打开的原因……但我想我还是采用了你的方法。通过使用StringReader建议,我可以测试对损坏的xml文件的反应,而不必提供损坏的文件。嗯,在这种情况下,我会考虑使用某种设置管理器类。。我通常不提倡单身,但这将是一个很好的候选人。然后,无论何时需要加载/保存设置,您都有一个单一的联系人。经理将负责打开文件并将流传递给阅读器。。。
[SetUp]
public void Setup()
{
Assume.That(File.Exists(SettingsReader.XML_SETTINGS_PATH));
}