Unit Testing – How to Test Correct Implementation of an Interface

unit testing

I have this problem with unit testing for years. Unit testing should test isolated units, that is, if we use interface/implementation vocabulary, it should test concrete implementation classes. Fine, let's do it. In a code that is the client of the interface, one should mock the interface to suit the tests. That's OK, let us do it where possible, too.

But then, in the productions code, there is some place where the actual implementation class is instantiated and used as the-instance-that-implements the interface. It may be factory methods, it can be somewhere else.

I have the problem how to actually test this glue between those two, correctly tested in isolation, layers. Using variants of instance of is brittle – not to say, the creator of the actual instance may be "smart" and choose different implementation based on circumstances. Even if not, it creates that instance using some configuration around.

So far, I either do not unit test in strict manner (so I do not do new Foo(directa, directb), but createApp(indirectA, indirectB).getFoo() instead), but that may not be proper unit testing. That does not test all the implementations, that test those-implementations-app-uses. Other approach I may see is to make tests of Foo implementation parametric, having a factory method makeFoo(a,b) and create subclasses for each implementations as well as one which creates those instances via an actual app.

Do you know of a good way on how to approach this?

In other words, the question may be simply "How to (unit) test glue code?"

Best Answer

The way you test glue code is by running an integration test.

The purpose of integration testing is to verify functional, performance, and reliability requirements placed on major design items. These "design items", i.e. assemblages (or groups of units), are exercised through their interfaces using black box testing, success and error cases being simulated via appropriate parameter and data inputs.

Simulated usage of shared data areas and inter-process communication is tested and individual subsystems are exercised through their input interface. Test cases are constructed to test whether all the components within assemblages interact correctly, for example across procedure calls or process activations, and this is done after testing individual modules, i.e. unit testing.

Related Topic