Question

I have an object that I want to test. It's supposed to call a method called ProcessFile(), which takes a filename as input. This method is mocked.

I can easily verify that the method is called the expected number of times. The actual filenames are randomly generated, however if you call ProcessFile() then clearly the file that it's supposed to be processing must exist on disk. If it doesn't, something is broken.

Currently the code under test is broken; it's sometimes calling the method with non-existent filenames. I really, really, really want the error message to say which file didn't exist.

I was able to sort-of kind-of get the test to detect that something is wrong like so:

mockProcessor.Verify(
  x => x.ProcessFile(It.Is<string>(s => s != null && File.Exists(s)),
  Times.Exactly(103)
);

Now the test fails if any of the files don't exist on disk. However, it fails claiming that the method wasn't called the required number of times. I understand why it says this, but that's a highly misleading message. The real problem is the files not existing on disk - a fact which the test output doesn't make especially clear. I know what's going on, but the next poor #### to work on this code may not have a clue.

What I really want is to check that the required number of invocations has occurred, and that in each such invocation, the specified file existed on disk. Any suggestions?

Was it helpful?

Solution 2

I came up with a solution using callbacks:

Action<string> callback = (file) => Assert.IsTrue(File.Exists(file));

mockProcessor.Setup(x => x.ProcessFile(It.IsAny<string>)).Callback(callback);

As it turns out, the bug I'm trying to hunt down depends on the fact that ProcessFile() deletes the file after processing. Naturally it's trivial to add that to the above callback.

So now I can go about actually trying to fix the bug...

OTHER TIPS

You could change s => s != null && File.Exists(s) into a statement body:

s => 
{
    if (s == null)
    {
        return false;
    }

    if (!File.Exist(s))
    {
        throw new FileNotFoundException(s);
    }

    return true;
}

Or extract a method and call that (s => FileNotNullAndExists(s)).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top