Problem unit testing functions that contain file I/O using Visual Studio Native cpp Unite Testing

452 Views Asked by At

I have this piece of code that counts the amount of instances a phrase exists within a text file. When I call this from a main() function, it works as expected.

When I try to write a Unit Test for it, it fails upon opening the file, returning -1 (see code below).

Here is the code for my countInstances function:

int countInstances(string phrase, string filename) {
    ifstream file;
    file.open(filename);
    if (file.is_open) {
        stringstream buffer;
        buffer << file.rdbuf();
        file.close();
        string contents = buffer.str();

        int fileLength = contents.length();
        int phraseLength = phrase.length();
        int instances = 0;

        // Goes through entire contents
        for(int i = 0; i < fileLength - phraseLength; i++){
            int j;

            // Now checks to see if the phrase is in contents
            for (j = 0; j < phraseLength; j++) {
                if (contents[i + j] != phrase[j])
                    break;
            }

            // Checks to see if the entire phrase existed
            if (j == phraseLength) {
                instances++;
                j = 0;
            }
        }

        return instances;
    }
    else {
        return -1;
    }
}

My Unit Test looks like:


namespace Tests
{       
    TEST_CLASS(UnitTests)
    {
    public:
        TEST_METHOD(CountInstances) {
            /*
                countInstances(string, string) :
                countInstances should simply check the amount of times that
                the passed phrase / word appears within the given filename
            */
            int expected = 3;
            int actual = countInstances("word", "../smudger/test.txt");
            Assert::AreEqual(expected, actual);
        }
        };
}

For the CountInstance Test I get the following message:

Message: Assert failed. Expected:<3> Actual:<-1>

Any ideas on where my issue comes from and how I could go about fixing it? Thanks.

2

There are 2 best solutions below

0
On

The fact that your tests depend on some file to be present in the file system makes your tests hard to maintain and understand, because the information for each test case is distributed. If you change the directory layout later, the tests may then fail again.

A better way to unit-test your code would be to extract the reading of the file content into a function of its own which, for example, returns the string with the file's content. For a start, put that function in a separate file.

In your tests you can then replace that function with a mock: The mock returns a string, but does not read it from a file - instead, your test code provides the string which the function shall then return. Since the original function was put into a separate file, you can create the test executable by not linking the original function, but the mocked function instead.

This way, you are in your tests not dependent on the file system. You can easily create a large number of test cases and have everything under control from within the test code.

There are more advance ways to achieve this, but this answer is just meant to give you a starting point. If you want to find out more, search for dependency injection, mocking, inversion of control.

0
On

Although having file system dependencies in unit tests is not ideal, you could simply create the unit test DLL(s) in a folder containing the test data files.

enter image description here