I joined an interesting presentation today about unit tests. Part of the presentation was related to dependency injection usage for unit testing. That brought to my mind again the benefits of meta-models.
Unit testing often faces the problem of having to instantiate objects that may impact the test itself or simply make the test impossible.
A sound example of this is when the method to be tested requires the instantiation of an object requiring, for instance, a database connection.
In this schema, we have 3 actors
- The function
- The caller
- The object (SomeObject) which cannot be instantiated.
One, now traditional, recipe is to use an Interface (instead of the specific object) as a function parameter. And, according to the context, instantiate and use an object that implements the defined interface. The figure below illustrates this.
Good solution… a little acrobatic, but OK… good.
A problem, though. We now have 6 actors (to code and maintain):
- The Function
- The caller
- The original 'true' object (SomeObject)
- The Interface
- The interface implementations (=2)!
On the other hand, testing a function may also need to instantiate a 'true' object context. In which case, we would have to rewrite (and recompileJ) our test code to instantiate a 'true' implementation when required.
A third point: in this solution, we defined the Interface to represent an abstraction of the original object. What if the original object itself was, for instance, a database record? This would then introduce a new actor in our playgroundJ
As Bjarne Stroustrup puts it:
"Any verbose and tedious solution is error-prone because programmers get bored" J
Meta-models may be a better way
In the current case, meta-models (see my previous posts) can be used to more simply describe all actors (object structures / methods / properties…).
Reminder: meta-models are closely related and enforced by Reflection (assemblies' meta-data). Through meta-models AND Reflection (namespace System.Reflection) developers can gain more flexibility to create versatile and scalable software.
In our present case, meta-models not only expose less actors to code and maintain, but also lower the complexity level of involved actors (for instance: maintaining database records instead of hard coding implementation).
The main goal for this approach is to ultimately write fewer universal methods to invoke and instantiate any object!
Will try to deliver a code sample in a future post. In the meantime, you may download meta-model sample code here!