Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit testing... how to improve it

I want to test a piece of code which returns an object.

I use NUnit and in a test class, I write a method to test if my method works fine...

[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);
}

This test does not work because MyObject does not override Equals method, and I don't want to override Equals method just for test purpose.

So I rewrite the test like this :

[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);
}

Ok, it works... but is this test is pertinent ? Moreover, there is a dependance to a file.

Is it pertinent to use a Mock Framework instead of ? And how to use it ?

Thank you !

like image 770
Florian Avatar asked Nov 22 '11 09:11

Florian


People also ask

What should a good unit test do?

Good unit tests should be reproducible and independent from external factors such as the environment or running order. Fast. Developers write unit tests so they can repeatedly run them and check that no bugs have been introduced.

How does unit testing improve software quality?

Good unit tests create testable code, which improves quality. That code will have fewer defects, which means fewer bug fixes, for faster project completion.


2 Answers

About that dependency on the file (that even appears not to be in the project!):

You could override that _myObjectParser.GetMyObjectFromLog to also accept a Stream. Then you can add that XML file as embedded resource and read it from the assembly.

like image 34
Hans Kesting Avatar answered Oct 22 '22 05:10

Hans Kesting


First of all, the method inside the parser should be name "Parse" instead of "Get".

Second of all, if you don't want the object itself to be able to compare itself to another, then it's perfectly fine to compare them just like you did (property by property). But this can be extracted into a helper method in the test class.

And lastly, you don't really want to tight-couple your parser with a file. You just want to parse text. If you want to include a static helper method that also opens a file and everything, that's your choice, but it shouldn't be a pure instance dependency.

[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);
}

Now both your class and your test are clearer and only have a single responsibility.

like image 75
Yam Marcovic Avatar answered Oct 22 '22 05:10

Yam Marcovic