Own Library Interface
Also known as: 'Skin and Wrap the API' [Working Effectively with Legacy Codeby Michael Feathers] How can we make a code testable, when the code depends on a library class, which can't be replaced by a 'Test Double'? We write our own interface that exactly mirrors the API of the library class. In our system under test (SUT) we use the interface instead of the library class itself.The code we want to test is the system under test (SUT). It references a depended-on component (DOC) library class.
Some library classes do not inherit from an interface, they do not declare their methods as virtual or they provide static methods, so it is not possible to introduce a Test Double to the SUT via Dependency Injection or Dependency Lookup to replace the library class during testing. This problem arises very often when we need to use system or third party libraries (like the .NET framework) where we can’t modify the library classes and have to use them as they are.
Library designers prefer to use class-based APIs instead of interfaces, because they can be evolved in later versions of the library. If they want to add members to a library interface in a later version , they would break existing code [Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Librariesby Abrams and Cwalina].
Very often the SUT can’t be tested together with the library class, because the library class can’t be used in the test environment. The reason may be that the library class will not return values needed for the test or executing it would have undesirable side effects.
How it Works
We write our own interface which mirrors the API of a library class we are using in our SUT. Our own interface does not need to contain the complete API of the library class but may contain only the subset we are requiring for our SUT. We implement a thin wrapper for the library class which inherits from our own interface. The wrapper will contain no logic. Each method can simply be forwarded to the library class, because the signatures of our own interface are the same as the library class. The SUT must use the interface instead of the library class itself. The SUT will be initialized with a concrete object via Dependency Injection or Dependency Lookup. In the production environment the thin wrapper is used. In the test environment we can replace the thin wrapper with a Test Double.When to Use It
We have to use the Own Library Interface when we use a third party library class in our SUT which has both of the two following characteristics:- The dependency on the library class prevents us from executing the SUT in a test environment. It may be plain impossible, too slow, too complex or too expensive to prepare a test environment for testing the SUT together with the library class.
- The library class can not be replaced by a Test Double, because it does not inherit from an interface, it does not declare its methods as virtual or it has static methods.
No comments:
Post a Comment