繁体   English   中英

单元测试......如何改进它

[英]Unit testing… how to improve it

我想测试一段返回对象的代码。

我使用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);
}

好吧,它有效......但这个测试是否相关? 而且,对文件有依赖性。

使用模拟框架而不是相关吗? 以及如何使用它?

谢谢 !

首先,解析器内部的方法应该是名称“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);
}

现在你的班级和考试都更清晰,只有一个责任。

关于对文件的依赖(甚至看起来不在项目中!):

您可以覆盖_myObjectParser.GetMyObjectFromLog以接受Stream。 然后,您可以将该XML文件添加为嵌入式资源,并从程序集中读取它。

绝对可以有一个文件的引用。 通常有两种测试类型:单元测试和集成测试。

集成测试总是与某些文件/数据库或其他任何东西进行交互。 在您的情况下,您可以通过模拟_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()上始终返回相同字符串的类。

然后,您可以使用您的类,它始终返回单元测试的静态字符串。

了解? 对不起我的英语不好 :)

是的,它看起来不错。 但是,如果在主项目中不需要它,则可以在测试项目中覆盖Equals 例如,通常我创建的类将私有和受保护的类提升为公共类。 因此,您可以自由扩展主项目,以便在测试项目中进行简单测试。

文件依赖是可以的,只需将此文件放在测试套件项目中即可。

单元测试的目的是测试代码的逻辑,上面的测试是做两件事:1。逻辑2.搜索

我说搜索是因为你试图匹配你在外部文件中创建的对象。 如果你这样做,问题是如果没有外部文件并且你不想要它,你的构建将开始中断。

解决方案:随时创建文件,但不创建物理文件,在内存中创建文件,然后插入需要匹配的对象,然后匹配该对象。

这样这个测试永远不会破坏。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM