C# 一个单元如何测试修改XML文档?

C# 一个单元如何测试修改XML文档?,c#,unit-testing,C#,Unit Testing,我甚至不知道如何开始为此方法创建单元测试: public override void ModifyXmlDocument(Foo foo, string nodeToChange, string newValue) { XmlDocument xmlDocument = new XmlDocument(); xmlDocument.Load(foo.XmlPathAndFileName); XmlElement rootElement = xmlDocument.Docu

我甚至不知道如何开始为此方法创建单元测试:

public override void ModifyXmlDocument(Foo foo, string nodeToChange, string newValue)
{
    XmlDocument xmlDocument = new XmlDocument();
    xmlDocument.Load(foo.XmlPathAndFileName);
    XmlElement rootElement = xmlDocument.DocumentElement;
    // rest of method (to modify an XML doc) here
}
该方法只需在XML文档中查找元素/节点,并使用用户提供的值对其进行更新。(该方法比此处显示的更复杂。)

我很难理解的是如何在不依赖硬盘的情况下执行这个方法。但是
xmlDocument.Load()
采用文件路径并从磁盘加载文件。在方法结束时,它将更新的文件保存回磁盘


如何使此方法单元可测试?

有几种方法可以做到这一点,但都需要重构代码
ModifyXmlDocument
需要将
XmlDocument
作为一个参数,然后您可以从那里开始模拟它

public void test_that_xml_is_loaded()
{
    var sut = new SUT();
    var xmldocumentfake = new Mock<XmlDocument>(){CallBase=true};
    xmldocumentfake.Setup(x=>x.LoadXml(It.IsAny<String>()));

    sut.ModifyXmlDocument(foo, nodeToChange, newValue, xmlDocumentfake.Object);

   xmldocumentfake.Verify(x=>x.LoadXml(It.IsAny<String>()), Times.Once());
}
public void测试\u是否加载了\u xml\u()
{
var sut=新sut();
var xmldocumentfake=new Mock(){CallBase=true};
Setup(x=>x.LoadXml(It.IsAny());
sut.ModifyXmlDocument(foo、nodeToChange、newValue、xmlDocumentfake.Object);
Verify(x=>x.LoadXml(It.IsAny()),Times.Once());
}
您还可以将
XmlDocument
包装在另一个类中,您可以将其编写为可修改的抽象。不过,你还是得把它交上来


此外,正如安东尼·佩格拉姆(Anthony Pegram)所暗示的,我的意思是:小心,不要违反规则。当测试太难编写时,通常会有人尖叫你违反了这一原则。

有几种方法可以做到这一点,但都需要重构代码
ModifyXmlDocument
需要将
XmlDocument
作为一个参数,然后您可以从那里开始模拟它

public void test_that_xml_is_loaded()
{
    var sut = new SUT();
    var xmldocumentfake = new Mock<XmlDocument>(){CallBase=true};
    xmldocumentfake.Setup(x=>x.LoadXml(It.IsAny<String>()));

    sut.ModifyXmlDocument(foo, nodeToChange, newValue, xmlDocumentfake.Object);

   xmldocumentfake.Verify(x=>x.LoadXml(It.IsAny<String>()), Times.Once());
}
public void测试\u是否加载了\u xml\u()
{
var sut=新sut();
var xmldocumentfake=new Mock(){CallBase=true};
Setup(x=>x.LoadXml(It.IsAny());
sut.ModifyXmlDocument(foo、nodeToChange、newValue、xmlDocumentfake.Object);
Verify(x=>x.LoadXml(It.IsAny()),Times.Once());
}
您还可以将
XmlDocument
包装在另一个类中,您可以将其编写为可修改的抽象。不过,你还是得把它交上来

此外,正如安东尼·佩格拉姆(Anthony Pegram)所暗示的,我的意思是:小心,不要违反规则。当测试太难编写时,通常会有人尖叫你违反了这一原则。

有几个选项:

  • 如果您使用的是VS2012 Ultimate,则可以使用Fakes创建一个垫片,该垫片将在XmlDocument打开文件时覆盖该行为
  • 测试时,使用单元测试部署一个示例XML文件。然后,当传入一个Foo实例时,使用该文件的路径
  • 请尝试XmlDocument.Load的备选方案之一,例如使用流或XmlReader。然后用一个可以重写的方法创建它
    • 有几个选项:

      • 如果您使用的是VS2012 Ultimate,则可以使用Fakes创建一个垫片,该垫片将在XmlDocument打开文件时覆盖该行为
      • 测试时,使用单元测试部署一个示例XML文件。然后,当传入一个Foo实例时,使用该文件的路径
      • 请尝试XmlDocument.Load的备选方案之一,例如使用流或XmlReader。然后用一个可以重写的方法创建它

      +1感谢您的提示;我试试看。我考虑过#2,但是文件在磁盘上是只读的,保存时会失败,我也不想保存它。请小心调用这些单元测试。特别是选项2……当您遇到其他依赖项时,您就是在进行集成测试。这没问题,但是要注意你写的东西以及速度成本和权衡+1谢谢你的提示;我试试看。我考虑过#2,但是文件在磁盘上是只读的,保存时会失败,我也不想保存它。请小心调用这些单元测试。特别是选项2……当您遇到其他依赖项时,您就是在进行集成测试。这没问题,但要注意你在写什么,速度成本和权衡+1我喜欢这两种选择,我会尝试它们。安东尼的回答到哪里去了?我认为他说得很好,他删除了它,因为它和我说的差不多。一旦你有了10公里以上的分数,你就可以看到被删除的答卷了。您在示例中使用的模拟框架是什么?看起来是最小起订量。我已经用了最小起订量,但还没有用你展示的方式。对不起,我是故意这么说的。确实是最低起订量。我认为这是一个非常基本的例子。+1我喜欢这两个选项,我会尝试它们。安东尼的回答到哪里去了?我认为他说得很好,他删除了它,因为它和我说的差不多。一旦你有了10公里以上的分数,你就可以看到被删除的答卷了。您在示例中使用的模拟框架是什么?看起来是最小起订量。我已经用了最小起订量,但还没有用你展示的方式。对不起,我是故意这么说的。确实是最低起订量。我认为这是一个非常基本的例子。