C# – Testing a class that uses external interface

cmockingunit testing

I have a class that internally uses an interface that is defined externally. Testing this class becomes difficult since I need to mock out this interface but I am required to reference the external library (which may be quite big) since the test is in a separate test project. Are there any ways to decouple this interface so that I can mock out the interface and test it without having to include the external project or is it an inherit problem of how my solution is setup?

Best Answer

Bob Martin's post The Clean Architecture recommends that your class's dependencies should point inward, not outward.

The overriding rule that makes this architecture work is The Dependency Rule. This rule says that source code dependencies can only point inwards. Nothing in an inner circle can know anything at all about something in an outer circle. In particular, the name of something declared in an outer circle must not be mentioned by the code in the an inner circle. That includes, functions, classes. variables, or any other named software entity.

Followed to the letter it means that your inner library would not even reference an outer library at all. Instead, it would define its own interfaces, and then additional libraries would create compositions that combine your inner classes with implementations of the interfaces it depends on.

(I've never seen this done. I'm not deriding it as impractical. It sounds awesome and I want to implement it on a large scale before I die.)

On a smaller scale you can get some of the benefits from ensuring that your classes depend on interfaces that you define, not on externally defined interfaces.

Using a really simple example, you might define your own logging interface, like

public interface ILogger
{
    void LogException(Exception ex); 
}

Now if a class needs to log exceptions, it depends only on that interface, not on a Microsoft interface or a Windsor interface, or whatever. Then if you're using some external logging library, you create an implementation of ILogger that wraps a call to that library.

What's great about this is that now you're achieving interface segregation. Your classes are less likely to depend on whatever giant interfaces the world hands to them, and more likely to depend on small interfaces that provide exactly what that class needs.

Then, going back to your original question, those interfaces will be easy to mock. They might even be so small that your find it easier to use simple test double classes instead of a mocking framework. I like using Moq but sometimes all of those setups become difficult to read. If I can just as easily write a class like PermissionsValidatorThatAlwaysReturnsTrue then I might go ahead and write the few extra lines of code. The time might be saved when someone sees that class used in a test, navigates it, and sees what it does, as opposed to trying to figure out which Mock is being used and how it's set up.

Related Topic