Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid or UnitTest the accidental use of a concrete singleton type instead of its abstraction with StructureMap

I recently had the following bug in my code which took me for ever to debug. I wanted to inject an instance based on its interface like this:

MovementController(IMotorController motorController)

However I accidentally used the concrete type like this:

MovementController(MotorController motorController)

The project still built and ran fine until I tried to access the motorController from the MovementController instance. Since the underlying implementation of IMotorController accesses hardware, it has to be a singleton or my locks code. However, since I had other classes with the injected IMotorController, I now had two instances MotorController in my object-graph, which both accessed the hardware over a serial connection. This caused an error, at run time at a much lower level, which took me forever to debug and find the true cause.

How can I avoid this type of bug or write a unit test for my StructureMap registry to catch this subtle bug?

like image 853
packoman Avatar asked Nov 09 '22 11:11

packoman


1 Answers

You could easily check for this using a static analysis tool like NDepend. With it you would just look for types that were controllers and then inspect their constructors and warn if you found any constructor parameters that were not interface types.


Just to refine the Steve answer, you could write a code rule that could look like: (with NDepend a code rule is a C# LINQ query prefixed with warnif count > 0)

// <Name>Don't use MotorController, use IMotorController instead</Name>
warnif count > 0
from m in Application.Methods 
where m.IsUsing ("NamespaceA.MotorController ") &&
      m.ParentType.FullName != "NamespaceB.ClassThatCanUseMotorController "
select m

The rule can be refined easily if there are zero or many ClassThatCanUseMotorController.

like image 111
ssmith Avatar answered Nov 14 '22 23:11

ssmith