Comment un conteneur IoC peut-il être utilisé pour les tests unitaires? Est-il utile de gérer des simulations dans une énorme solution (plus de 50 projets) à l'aide d'IoC? Des expériences? Des bibliothèques C # qui fonctionnent bien pour l'utiliser dans des tests unitaires?
De manière générale, un conteneur DI ne devrait pas être nécessaire pour les tests unitaires, car les tests unitaires consistent à séparer les responsabilités.
Considérons une classe qui utilise l'injection de constructeur
public MyClass(IMyDependency dep) { }
Dans toute votre application, il se peut qu'il y ait un énorme graphique de dépendance caché derrière IMyDependency
, mais dans un test unitaire, vous l'aplatissez en un seul Test Double .
Vous pouvez utiliser des mocks dynamiques comme Moq ou RhinoMocks pour générer le test double, mais ce n'est pas obligatoire.
var dep = new Mock<IMyDependency>().Object;
var sut = new MyClass(dep);
Dans certains cas, un conteneur auto-moqueur peut être agréable à avoir, mais vous n'avez pas besoin d'utiliser le même conteneur DI que l'application de production utilise.
Comment un conteneur Ioc peut-il être utilisé pour des tests unitaires?
IoC appliquera des paradigmes de programmation qui rendront les tests unitaires isolés (c'est-à-dire en utilisant des simulations) plus faciles: utilisation d'interfaces, pas de nouveau (), pas de singletons ...
Mais l'utilisation du conteneur IoC pour les tests n'est pas vraiment une exigence, il fournira simplement certaines installations, par exemple injection de simulacres mais vous pouvez le faire manuellement.
Est-il utile de gérer des simulations dans une énorme solution (plus de 50 projets) à l'aide d'IoC?
Je ne sais pas ce que vous entendez par gérer les simulations à l'aide d'IoC. Quoi qu'il en soit, les conteneurs IoC peuvent généralement faire plus que simplement injecter des simulations lorsqu'il s'agit de tests. Et si vous avez un support IDE décent qui rend le refactoring possible, pourquoi ne pas l'utiliser?
Une expérience?
Oui, sur une énorme solution, vous avez plus que jamais besoin d'une solution non sujette aux erreurs et à la refactorisation (c'est-à-dire soit via un conteneur IoC sûr de type ou bon IDE).
J'utilise souvent un conteneur IoC dans mes tests. Certes, ce ne sont pas des "tests unitaires" au sens pur. IMO Ils sont plus BDDish et facilitent le refactoring. Les tests sont là pour vous donner confiance en refactoriser. Des tests mal écrits peuvent être comme verser du ciment dans votre code.
Considérer ce qui suit:
[TestFixture]
public class ImageGalleryFixture : ContainerWiredFixture
{
[Test]
public void Should_save_image()
{
container.ConfigureMockFor<IFileRepository>()
.Setup(r => r.Create(It.IsAny<IFile>()))
.Verifiable();
AddToGallery(new RequestWithRealFile());
container.VerifyMockFor<IFileRepository>();
}
private void AddToGallery(AddBusinessImage request)
{
container.Resolve<BusinessPublisher>().Consume(request);
}
}
Plusieurs choses se produisent lors de l'ajout d'une image à la galerie. L'image est redimensionnée, une miniature est générée et les fichiers sont stockés sur AmazonS3. En utilisant un conteneur, je peux plus facilement isoler uniquement le comportement que je veux tester, qui dans ce cas est la partie persistante.
Une extension de conteneur à mockage automatique est utile lorsque vous utilisez cette technique: http://www.agileatwork.com/auto-mocking-unity-container-extension/
L'utilisation de conteneurs capables de résoudre des services non enregistrés/inconnus tels que SimpleInjector , DryIoc (sa mine) peut renvoyer des simulations pour des interfaces non encore implémentées.
Ce qui signifie que vous pouvez commencer le développement avec la première implémentation simple et ses dépendances simulées, et les remplacer par des choses réelles au fur et à mesure de votre progression.