Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to unit-test a class which needs a specific file to be present

I'm currently trying to learn proper unit-test. So now I'm trying to write unit-tests for a class that should map data from an XML-File to the proper objects. Of course all functionality of the class is dependent on the existence of the corresponding XML-file. The XML-file is loaded in the constructor of the class.

I'm using C# with NUnit. So far I've got two tests:

[Test]
public void ShouldAllowInstanceToBeCreatedWhenXMLFileIsPresent()
{
    if (File.Exists(SettingsReader.XML_SETTINGS_PATH))
    {
        SettingsReader settingsReader = new SettingsReader();
        Assert.AreNotEqual(null, settingsReader);
    }
}

[Test]
[ExpectedException("Telekanzlei.Clientmanager.XMLDataLayer.XMLFileNotFoundException")]
public void ShouldThrowExceptionWhenXMLFileIsNotPresent()
{
    if (!File.Exists(SettingsReader.XML_SETTINGS_PATH))
    {
        SettingsReader settingsReader = new SettingsReader();
    }
        else
            throw new XMLFileNotFoundException();
    }

I'm not sure if checking the existence of the file in the test is a proper way to go, so any suggestions on those test are welcome too. But my question is, how to proceed with the following tests. Obviously all following tests are going to fail, if the XML-file is not present.

So do I assume that the XML-file is present, while keeping in mind, that a failing test could just mean that it's not? That wouldn't seem right to me.

Is there a general pattern, to handle a problem like this?

Thx for any help

edit: rewrote the second test, as it was failing if the file was actually present...

edit2: May it is helping to tell you, what the SettingsReader actually does. So far it looks like this:

public class SettingsReader
{
    public static readonly string XML_SETTINGS_PATH = "C:\\Telekanzlei\\Clientmanager_2.0\\Settings.xml";

    public XElement RootXElement { get; private set; }

    public SettingsReader()
    {
        if (!File.Exists(XML_SETTINGS_PATH))
            throw new XMLFileNotFoundException();
        using (var fs = File.OpenRead(XML_SETTINGS_PATH))
        {
            RootXElement = XElement.Load(fs);
        }
    }


}

I'm not sure, but I guess a StreamReader wouldn't be the way to go here, would it?

like image 768
Tobi Avatar asked Mar 02 '12 21:03

Tobi


People also ask

Should unit tests be in a separate file?

You'll put unit tests in the src directory in each file with the code that they're testing. The convention is to create a module named tests in each file to contain the test functions and to annotate the module with cfg(test) .

Should unit tests read files?

Strictly speaking, unit tests should not use the file system because it is slow. However, readability is more important.

How do you unit test classes which create new objects?

The first step is to import Mockito dependencies into your code. Now let us see an example of how to test the class. Let us assume the below is the class that we want to test. Below is the sample class of the object that is instantiated in ClassToBeTested.


1 Answers

The problem is not with your unit tests but with the design of the class. I'd suggest refactoring the class so it doesn't open the file but instead operates on a stream. Then your unit tests could simply replace a file stream for a memory stream - simples! :)

public class SettingsReader()
{
    public SettingsReader(System.IO.StreamReader reader)
    {
        // read contents of stream...
    }
}

// In production code:
new SettingsReader(new StreamReader(File.Open("settings.xml")));

// In unit test:
new SettingsReader(new StringReader("<settings>dummy settings</settings>"));

Remember, opening a file and parsing settings data are two very different concerns.

like image 142
MattDavey Avatar answered Nov 15 '22 21:11

MattDavey