I have an extension method that does a .ToMessageBox(..). As you might imagine, when I try to test this with a unit test, it pops up a message box and hangs the unit test framework until I click OK. This is not very ideal. However, I want to be able to unit test this and it’s convenience overloads.
If you look at the MessageBox class, it does not implement any interfaces nor does it inherit from any base class. Worse, it has no constructors so I can’t inherit from it either.
From searching around, I saw a reference to someone getting around this with a dependency property – in a very confusing way. However, it got me thinking that I might get around this problem with delegates. This bent my brain at first, but now it seems so obvious!
The plan is this: I create a delegate that matches the signature of the specific implementation of MessageBox.Show that I need. Then, at run-time, I can point that delegate at the real MessageBox.Show, or to a mock/non-UI method that I control in my unit tests.
This might be kind of confusing. Picture this, instead of pointing to MessageBox.Show(..), I am going to define a signature that matches that call – that’s a delegate. That then allows me to point that “function pointer” to either the real Message>Show(..) because the signature matches, or I could point it to a mock one that I create.
Here is some code:
The Actual Code That Uses The MessageBox:
On like 24, I was calling MessageBox.Show(..) – but now I’m invoking the delegate instead.
By default, as provided in the static constructor on line 9, this delegate points to the REAL MessageBox.Show. However, I expose that delegate out as a property of CurrentMessageBoxShow. So, in my unit tests, I can override this with my own implementation and this ToMessageBox(..) method will be none the wiser:
As you can see on line 9, I override the default CurrentMessageBox with my own anonymous delegate that simply sets a flag (line 13) and returns a DialogResult (line 14).
This approach let’s me fully test my code without having to actually invoke a real MessageBox.Show(..)!
If you are new to delegates, this is likely very confusing. However, if you dabble with delegates – this is a classic example of having the right tool for the job. Without using delegates, I literally cannot think of any other way that I could unit test this code without popping up an actual messagebox. When the original implementation left me with my hands tied, there were no other alternatives.
Anyhow, hopefully this helps – this idea could prove to be very useful when trying to unit test against anything that uses external resources, but where there is no interface, common base class, and when the implementation is sealed.