Interface-based design leads to good Unit Tests because you can more easily have a separation of concerns, limit the test to one object, and eliminate dependencies by not having to have “real” dependencies available to test a portion of your code.
I am going to explain this by example.
First, let me remind you of some rules for writing good Unit Tests:
- You don’t touch the system so Unit Tests can run on a stable build device without corrupting the build system.
- You don’t have external dependencies so the build system can run in an isolated environment.
- The tests should run quickly.
- Each test should test one thing only.
Imagine you have code that tests authenticating to a UNC path. You have these two classes:
BusinessObject contains an instance of NetworkShare. The code is not really significant as this is theoretical. We’ll get to code in the next few articles.
You need to write Unit Tests for BusinessObject.cs.
Why is this a problem? Because it requires a system with a UNC share to run the class and so testing is difficult.
Now, imagine that BusinessObject.cs didn’t actually have an instance of NetworkShare, but instead an Interface was created called IAuthenticateRemotely. And Your code now includes these files.
- NetworkShare : IAuthenticateRemotely
Now BusinessObject has an instance of IAuthenticateRemotely instead of an instance of NetworkShare. Now you can write Unit Tests for the BusinessObject class by simply creating any fake class in your Unit Test code that implements IAuthenticateRemotely. Your test class would simply be a fake. Lets say the IAuthenticateRemotely had a bool Authenticate() function. You would create a fake class for your test and implement this function as follows.
public bool Authenticate()
Notice that the function doesn’t actually do anything. That is because a Unit Test for the BusinessObject class only needs to test the BusinessObject class.
Please feel free to make any comments as necessary.
Return to C# Unit Test Tutorial