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?
C# – Testing a class that uses external interface
cmockingunit testing
Related Solutions
Make a big decision first: compile time or runtime?
If you do want to use assembly references, they are compile-time only. Then you can use #if directives in your code and you can use MSBuild tricks (edit the csproj file outside Visual Studio) to conditionally have the assembly reference. MSBuild is a very powerful tool, and if you are careful, it won't mess too much with Visual Studio. Or you can just have multiple csproj files, living in the same directory, using (almost) the same source files, and different references. This all happens at compile time.
A completely different approach is doing the reference loading during runtime, that's why they invented reflection. You are lucky if the external reference implements a common interface because once you get the type with reflection, you can cast it to your interface and use it normally. Otherwise, you are stuck with Invoke()
-ing MethodInfo
-s. Or, if your requirements allow it, you can create a very small adapter layer assembly between the external library and yours, as a 3rd assembly. If you need to use the external library, you load your adapter assembly dynamically, cast it to an interface, and use the external library through that layer, no Invoke()
anywhere.
TLDR: Despite the difficulty, you should stub the service and use for client unit testing.
I'm not as certain that the "job of a remote API client is to issue certain calls, no more, no less...", unless the API only consists of endpoints which always return a fixed status, and neither consume nor produce any data. This would not be the most useful API...
You'd also want to check that the client not only sends the correct requests, but that it properly handles response content, errors, redirects, etc. And test for all these cases.
As you note, you should have integration tests that cover the full stack from wrapper -> client -> service -> DB and beyond, but to answer your main question, unless you have an environment where integration tests can be run as part of every CI build without a lot of headaches (shared test databases, etc.), you should invest the time in creating a stub of the API.
The stub will let you create a working implementation of the service, but without having to implement any layer below the service itself.
You could consider using a DI-based solution to accomplish this, with an implementation of the Repository pattern underneath the REST resources:
- Replace all functional code in the REST handlers with calls to an IWhateverRepository.
- Create a ProductionWhateverRepository with the code that was extracted from the REST resources, and a TestWhateverRespository which returns canned responses for use during unit testing.
- Use the DI container to inject either the ProductionWhateverRepository or TestWhateverRepository DLL/class, etc. depending on configuration.
Anyway, unless stubbing and/or refactoring the service is out of the question either politically or practically, I'd probably undertake something similar to the above. If not possible, then I'd make sure to have really good integration coverage and run them as often as possibly given your available test setup.
HTH
Best Answer
Bob Martin's post The Clean Architecture recommends that your class's dependencies should point inward, not outward.
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
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 whichMock
is being used and how it's set up.