Often when we want to write unit tests, we need to work with third-party code. This code can't be changed. When we bump into these issues, we need to use a mocking framework. Moq is a great free mocking library, however, Moq can't mock non-virtual methods or properties. This can be a pain, however, you can usually get your code under test by taking a different path. I have seen a lot of new developers get stuck for many hours/days when they encounter this situation. For some reason, many people focus on trying to change the way Moq works or finding some magic bullet to change the unchangeable code, instead of rearchitecting the code slightly.
In order to get your code testable.. the tip is you'll need to rewrite YOUR code. I work with a CMS called Episerver. When you work with their API and you can't mock the PageData
class. A code snippet might look like this:
No matter what you do, this code can not be mocked. Do not waste your time trying to fix the unfixable. I can't rewrite the third-party code. My website needs to use this code, so instead of giving up and leaving my code untestable let us refactor things to a design pattern! One way to refactor the code is to wrap it within wrapper class. This wrapper class will need to implement an interface./ The wrapper will simple performs the logic that can't be mocked. By moving the call into a class that does have an interface, the wrapper class can be mocked now! and then mock that interface instead, so:
I can then rewrite the code like so:
In my code, instead of calling IsModified
directly, I access thee data from the new wrapper class:
I've now mocked something that's unmockable 💥If you are new to mocking and you're reading this, this is a great design pattern to have in your toolbox 🧰
When you struggle to unit test some code, it is usually easier to refactor your code into a more testable way. Adapters and Facades are two design patterns designed to achieve this sort of thing. If you're sitting in front of your PC struggling to find a way to add some mock data into something that you can't change, I challenge you to look at your code and think how you can refactor it, so that you can mock that part of the code yourself. Happy Coding 🤘