6

当我在测试中运行以下代码时,

Mock<XmlWriter> mockXmlWriter = new Mock<System.Xml.XmlWriter>();
Language language = Language.GetLangauge(langId);
language.WriteXml(mockXmlWriter.Object);
mockXmlWriter.Verify(writer => writer.WriteAttributeString("ID", language.LanguageID.ToString()));

Moq 可以理解地引发以下异常:System.NotSupportedException : Invalid verify on a non-virtual (overridable in VB) member: writer => writer.WriteAttributeString("ID", .language.LanguageID.ToString()).

愚蠢的抽象XmlWriter仍然有一些非抽象、非虚拟的方法,比如WriteAttributeString():(

我寻找 anXmlWriterBase或 a System.Xml.Abstractions,就像我寻找HttpContextand Co. 一样,但什么也没找到 :(

我将如何克服这个问题,以便我可以测试我的WriteXml方法是否正在做它应该做的事情?

4

1 回答 1

5

根据经验,模拟你不拥有的类是一个坏主意,因为你无法完全控制它们,这可能会导致问题(比如你的)。

我认为您可以在这里安全地使用 real XmlWriter,它将其输出写入 aMemoryStream并简单地断言流包含预期的 XML:

// arrange
MemoryStream underlyingStream = new MemoryStream();
XmlWriter xmlWriter = XmlWriter.Create(underlyingStream);
Language language = Language.GetLangauge(langId);

// act
language.WriteXml(xmlWriter);

// assert
underlyingStream.Position = 0;
using (StreamReader streamReader = new StreamReader(underlyingStream)
{
    string createdXml = streamReader.ReadToEnd();
    Assert.That(createdXml, Is.EqualTo("expectedXml"));
}

断言部分可以很好地重构为辅助方法。最近写了一个处理 XML 创建的代码,我对它很感兴趣 - 起初,我的测试是基于模拟的,而且本质上,它们是生产代码的精确副本。幸运的是,在进行到一半时,我决定将整个事情重构为类似于我的示例中的样式,这确实很有帮助——测试现在变得不那么脆弱了,一切都变得更简单了。

于 2012-12-13T19:25:24.643 回答