我想测试一段返回对象的代码。
我使用NUnit,在测试类中,我编写了一个方法来测试我的方法是否正常工作......
[Test]
public void GetMyObjectFromLog()
{
string _xmlFilePath = @"C:\XmlFile.xml";
MyObjectParser _myObjectParser = new MyObjectParser();
MyObject _mockMyObject = new MyObject
{
Title = "obj",
Name = "objName"
}
MyObject _myObject = _myObjectParser.GetMyObjectFromLog(_xmlFilePath);
Assert.AreEqual(_mockMyObject , _myObject);
}
此测试不起作用,因为MyObject
未覆盖Equals
方法,并且我不想仅仅为了测试目的而覆盖Equals
方法。
所以我改写了这样的测试:
[Test]
public void GetMyObjectFromLog()
{
string _xmlFilePath = @"C:\XmlFile.xml";
MyObjectParser _myObjectParser = new MyObjectParser();
MyObject _myObject = _myObjectParser.GetMyObjectFromLog(_xmlFilePath);
Assert.AreEqual("obj", _myObject.Title);
Assert.AreEqual("objName", _myObject.Name);
}
好的,它有效......但这个测试是否合适?此外,还有一个文件的依赖。
使用模拟框架而不是?以及如何使用它?
谢谢!
答案 0 :(得分:5)
首先,解析器中的方法应该是名称“Parse”而不是“Get”。
其次,如果你不希望对象本身能够将自己与另一个对象进行比较,那么就像你所做的那样(属性属性)来比较它们就完全没问题了。但是这可以在测试类中提取到辅助方法中。
最后,你真的不想将解析器与文件紧密结合。你只想解析文本。如果你想包含一个静态帮助方法,它也可以打开一个文件和所有东西,这是你的选择,但它不应该是纯实例依赖。
[Test]
public void ParsesObjectFromXml()
{
string xmlInput = " ... ";
MyObjectXmlParser parser = new MyObjectXmlParser();
MyObject expected = new MyObject() {Title = "obj", Name="objName"};
AssertMyObjectsAreEqual(expected, parser.Parse(xmlInput));
}
private bool AssertMyObjectsAreEqual(MyObject expected, MyObject actual)
{
Assert.AreEqual(expected.Title, actual.Title);
Assert.AreEqual(expected.Name, actual.Name);
}
现在你的班级和考试都更清晰,只有一个责任。
答案 1 :(得分:2)
关于对文件的依赖(甚至看起来不在项目中!):
您可以覆盖_myObjectParser.GetMyObjectFromLog
以接受Stream。然后,您可以将该XML文件添加为嵌入式资源,并从程序集中读取它。
答案 2 :(得分:1)
绝对可以获得对文件的引用。通常有两种测试类型:单元测试和集成测试。
集成测试总是与某些文件/数据库或其他任何东西进行交互。在您的情况下,您可以通过模拟_myObjectParser.GetMyObjectFromLog来改进测试。
您可以自己编写模拟或使用像rhinomocks这样的框架。一本关于nunit / rhinomocks的好书是:单元测试的艺术。
GetMyObjectFromLog的更好的可测试版本可能如下所示:
public MyObject GetMyObjectFromLog(IMyXmlReader reader)
{
var xmlData = reader.GetData();
//make your object here
var obj = new MyObject(xmlData);
return obj;
}
然后,您可以实现2个实现接口IMyXmlReader的新类,一个从生成代码的文件中读取的类,以及一个在GetData()上始终返回相同字符串的类。
然后,您可以使用您的Class,它始终为您的单元测试返回静态字符串。
明白了吗?对不起我的英文:)
答案 3 :(得分:1)
是的,看起来不错。但是,如果在主项目中不需要它,则可以覆盖测试项目中的Equals
。例如。通常我创建的类将私有和受保护的类提升为公共类。因此,您可以自由扩展主项目,以便在测试项目中进行简单测试。
文件依赖性正常,只需将此文件放入测试套件项目中即可。
答案 4 :(得分:0)
单元测试的目的是测试代码的逻辑,上面的测试是做两件事: 1.逻辑 2.搜索
我说搜索是因为您正在尝试匹配您在外部文件中创建的对象。如果你这样做,问题是如果没有外部文件并且你不想要它,你的构建将开始中断。
解决方案: 随时创建文件,但不创建物理文件,在内存中创建文件,然后插入需要匹配的对象,然后匹配对象。
这种测试永远不会破坏。