Xml解析器类的单元测试

本文关键字:单元测试 Xml | 更新日期: 2023-09-27 17:49:30

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

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

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

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

我真正的问题是,当Visual Studio中的单元测试框架告诉我们是否所有的测试都通过时,有一些这样的消息框弹出是否ok。

或者我只需要返回一个bool值,然后GUI类显示适当的错误消息。

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

如果你能给我一些关于我的设计和单元测试的建议,我将非常感激。

同时,我也承认在写完需要测试的类之后写单元测试是一个很大的错误,我知道应该反过来写

Xml解析器类的单元测试

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,也可以使用模拟框架并验证它是否被调用了一定次数。下面是一个使用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));

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

我喜欢测试驱动的开发,但是在编写实现之后编写测试也是可行的。