I have the following classes:
public class MyClass
{
public void MyMethod()
{
try
{
...
save data to file
...
}
catch (Exception exception)
{
ErrorDisplay.ShowErrorMessage("MyMethod", exception);
}
}
}
public class ErrorDisplay
{
public static ShowErrorMessage(string methodName, Exception exception)
{
if (exception is IOException)
MessageBox.Show(methodName + " : " + GetIODisplayMessage());
else if ...
...
else
...
}
public static string GetIODisplayMessage()
{
return "IO error";
}
....
}
I need to write a unit test in witch i will mock the IOException and i need to check that
GetIODisplayMessage() method is being called. Is there a way to test if a method is called?
Or maybe another idea on how to make a unit test for my case?
Thanks.
As mentioned above, using the static ErrorDisplay causes a number of problems with testing and injecting in an implementation of IErrorDisplay would solve some of them but not all (see MessageBox below). However…
Static + Interface
If you need to keep the static class ErrorDisplay and don’t want to shell out for TypeMock you can add a level of indirection
You get to keep the existing calls to ErrorDisplay, but they are now more replaceable and testable.
It is not a perfect solution but, if maintaining legacy code, it lets you add some testability without having to do major rework.
MessageBox
You have another problem with running unit tests on ErrorDisplay; you will have a MessageBox appearing. Not good if trying to run tests in a test harness (or as part of a build).
Again indirection is your friend. You can replace the MessageBox.Show() call with a call to a MessageDisplayService.Show(). The default implementation can call message box, a dummy one can be used for testing (either a mock or simple do nothing implementation)
Unit Testing
What are your unit boundaries for testing?
It looks from the question that you want to run a test against MyClass::MyMethod(), cause an IOException and see that GetIODisplayMessage() is invoked. If I mis-understood, please skip the next section 🙂
Are you planning to do this for every class/method where an IOException can occur?
Are you planning to do this for every class/method where each of the other exception types handled by ErrorDisplay can occur?
This is a lot of work to which simply re-tests the ErrorDisplay code again and again.
The boundaries I would see are
MyClass::MyMethod
If an Exception occurs, it calls ErrorDisplay.ShowErrorMessage() passing in “MyMethod” and the exception.
Anything after that is out of its hands and should not be part of the unit tests.
ErrorDisplay.ShowErrorMessage()
If it is called with an IOException then it shows the message that it gets by calling GetIODisplayMessage().
This is independent (as written above) of the calling code and can be unit tested separately.
ErrorDisplay.GetIODisplayMessage()
Returns the correct error message. OK, a bit of overkill if the value is hardcoded but shows the principle.
When testing MyClass::MyMethod, we want to verify that when an exception occurs, the error display code is called passing in the correct method name and exception.
When testing ErrorDisplay.ShowErrorMessage(), we verify we get the correct message for the exception type that we call the MessageDisplayService.Show() with
methodname + “:” + <>
we don’t need to test the text of the IODisplayMessage here.
When testing ErrorDisplay.GetIODisplayMessage() we check that it returns the correct message.
Hope this is useful,
Alan.