Xml Parser类的单元测试

时间:2011-04-06 17:07:25

标签: c# xml unit-testing

我有一个类,它使用C#中的XmlReader和XmlReaderSettings类来根据模式验证Xml文件。由于我的应用程序涉及从数据库中读取Xml数据,因此我决定在MessageBox中向用户显示错误。因此,任何验证错误以及抛出的任何异常都将在MessageBox中显示一个字符串“解析时出错”。

我还有一个布尔变量,它返回解析是否成功。

现在,我正在使用Assert中Parse函数返回的布尔值,同时让解析函数解析有效和无效的Xml文件。

因此,在运行测试用例套件时,我将这些消息框堆叠在另一个窗口中。

我遇到的真正问题是,当Visual Studio中的单元测试框架告诉我们是否所有测试都通过时,可以弹出大量这些消息框。

或者是我需要返回bool值然后GUI类显示相应的错误消息的情况。

Q2。另外,如果我确实需要检查特定字符串是否被正确解析并存储到数组中,我可以将主类子类化以添加一些可以帮助我更好地编写单元测试的功能吗?

我真的很感激我的设计和单元测试的一些建议。

另外,我确实接受在写下我需要测试的课程后编写单元测试时犯了一个大错误,我知道它应该反过来。

2 个答案:

答案 0 :(得分:6)

解析Xml和显示错误消息是一个单独的问题,因此您的解析器不应该知道错误消息的显示方式。

根据您的需要,有以下几种选择:

<强>例外

我经常按照规则生活:“如果一个方法无法完成它的工作,就抛出异常”。如果您需要在第一个错误处停止,则可以使用例外。

从单元测试的角度来看,如果传入非法数据,请使用[ExpectedException]属性验证代码是否抛出异常。

[TestMethod, ExpectedException(typeof(ParserValidationException))]
public void IllegalDataShouldThrowValidationErrors()
{
    var parser = new MyParser();
    parser.Parse( dataThatContainsErrors );
}

但是,如果您需要忽略非法数据并报告错误,您可能需要采用不同的方法。

专业退货类型

如果您需要收集所有错误,最好将解析后的结果和错误保存在一起作为对象。

public class ParsedResult<T>
{
    public T Result;
    public List<string> Warnings;
}

从单元测试的角度来看,如果传入非法数据,则应验证警告列表是否为空。

[TestMethod]
public void ParsedResultsForIllegalDataShouldContainWarnings()
{
    var parsedResult = new MyParser.Parse<Foo>( dataThatContainsErrors );

    Assert.IsNotNull(parsedResult);
    Assert.IsNotNull(parsedResult.Result);
    Assert.AreEqual(1, parsedResult.Warnings.Count);
}

错误报告

将协作者传入对象并让其报告其结果。

public ObjectToReturn Parse(string xml, IProgressReporter progress)
{
     // create xml reader
     // read values from xml
     // if a value is invalid, log it
     progress.AddMessage( "property x was invalid. ")
}

进度报告器可以是MessageBox的包装器,也可以是控制台输出,记录器等。从单元测试的角度来看,您可以创建一个捕获消息的Test Double,也可以使用mock框架并验证它被调用了一定次数。这是一个使用Moq的例子。

var mockReporter = new Mock<IProgressReporter>();
IProgressReporter reporter = mockReporter.Object;

var parser = new MyParser();
var illegalData = // your illegal data;

var result = parser.Parse( illegalData, parser);

Assert.IsNotNull(result, "The value was not parsed correctly.");
mockReporter.Verify( r => r.AddMessage( It.IsAny<string>() ), Times.AtLeast(1));

答案 1 :(得分:2)

我认为您不应该使用MessageBox进行错误报告,而是将错误传递为List<string>并让GUI显示它们。

我喜欢测试驱动开发,但在编写实现后编写测试也很有效。对我来说,在写完之后会更加努力。

相关问题