Bei dem Versuch, auf die D in SOLID
Dependency Inversion Prinzip einzuhalten, wo ein „auf Abstraktionen abhängen sollte. Verlassen Sie sich nicht auf Konkretionen
für ein Projekt. In diesem Fall, Asp.Net-MVC5, wollte ich sicherstellen, dass alle Controller (MVC und WebAPI2) diesem Muster folgen, wo sie nicht von Konkretionen abhängig sind.
Die ursprüngliche Idee kam von einem Artikel, den ich gelesen hatte, wo ein Komponententest erstellt wurde, um alle Controller zu scannen, um sicherzustellen, dass sie eine explizite Autorisierung definiert hatten. Ich habe ähnliche Überlegungen angestellt, indem ich überprüft habe, ob alle Controller Konstruktoren haben, die von Abstraktionen abhängen.
[TestClass]
public class ControllerDependencyTests : ControllerUnitTests {
[TestMethod]
public void All_Controllers_Should_Depend_Upon_Abstractions() {
var controllers = UnitTestHelper.GetAssemblySources() //note this is custom code to get the assemblies to reflect.
.SelectMany(assembly => assembly.GetTypes())
.Where(t => typeof(IController).IsAssignableFrom(t) || typeof(System.Web.Http.Controllers.IHttpController).IsAssignableFrom(t));
var constructors = controllers
.SelectMany(type => type.GetConstructors())
.Where(constructor => {
var parameters = constructor.GetParameters();
var result = constructor.IsPublic
&& parameters.Length > 0
&& parameters.Any(arg => arg.ParameterType.IsClass && !arg.ParameterType.IsAbstract);
return result;
});
// produce a test failure error mssage if any controllers are uncovered
if (constructors.Any()) {
var errorStrings = constructors
.Select(c => {
var parameters = string.Join(", ", c.GetParameters().Select(p => string.Format("{0} {1}", p.ParameterType.Name, p.Name)));
var ctor = string.Format("{0}({1})", c.DeclaringType.Name, parameters);
return ctor;
}).Distinct();
Assert.Fail(String.Format("\nType depends on concretion instead of its abstraction.\n{0} Found :\n{1}",
errorStrings.Count(),
String.Join(Environment.NewLine, errorStrings)));
}
}
}
Also das folgende Beispiel gegeben. (Man beachte ich das MVC angepasst)
public class MovementController : Controller {
public MovementController(MotorController motorController) {
//...
}
}
public interface IMotorController {
//...
}
public class MotorController : IMotorController {
//...
}
der Unit-Test fehlschlagen würde mit ...
Result Message: Assert.Fail failed.
Type depends on concretion instead of its abstraction.
1 Found :
MovementController(MotorController motorController)
Das ist für mich gearbeitet, weil ich eine gemeinsame Art hatte zu suchen mit dem IController
und ApiController
.
Es gibt Raum für Verbesserungen im Test, aber es sollte ein guter Ausgangspunkt für Sie sein.
Mal sehen, ich verstehe: Sie wollen einen Komponententest, um zu überprüfen, dass Ihre Controller nur Schnittstellen als Konstruktor Argumente haben? Was für ein Projekt ist das? MVC, winform, wpf ...? – Nkosi