2011-04-06 67 views
3

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

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

现在,我使用Parse函数在Assert中返回的布尔值,同时解析函数解析有效和无效的Xml文件。因此,在运行测试用例套件时,我将这些堆栈的消息框堆积在另一个窗口中。

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

或者是我只需要返回一个布尔值,然后GUI类显示相应的错误消息的情况。 Q2302。另外,如果我确实需要检查一个特定的字符串是否被正确解析并存储到一个数组中,我可以继承这个主类来添加一些可以帮助我更好地编写单元测试的功能吗?

我真的很感谢一些关于我的设计和单元测试应该如何的建议。

另外,我承认在编写单元测试后,我写了一个很大的错误,之后我写下了需要测试的类,我知道它应该是相反的。

回答

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的包装,或者它可能是一个控制台输出,记录仪等。从单元测试的角度来看,你可以创建一个测试双捕获的消息,或者你可以使用模拟框架并验证它被称为一定的次数。这是一个使用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)); 
2

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

我喜欢测试驱动的开发,但是在编写实现后编写测试也可以。对我来说,写下更多的努力。