Pourquoi voudriez-vous écrire des tests unitaires pour les contrôleurs?

22

Pour moi, c'est un test unitaire totalement hors de propos et je ne comprends pas pourquoi quelqu'un aurait passé du temps à l'écrire, car il y a très peu de valeur à en tirer. Je saurais parfaitement si ce contrôleur a renvoyé le type voulu en exécutant la méthode dans un navigateur. Vraiment, croyez-vous qu'un test est nécessaire pour cela et pourquoi?

public class ConstituencyControllerTests
{
    private ConstituencyController _constituencyController;
    private Mock<IConstituencyService> _IConstituencyServiceMock;

    public ConstituencyControllerTests() {
        _IConstituencyServiceMock = new Mock<IConstituencyService>();
    }

    [Test]
    public async Task I_Check_For_Return_Type_And_Result() {
        _constituencyController = new ConstituencyController( _IConstituencyServiceMock.Object );

        var result = await _constituencyController.Get();
        var content = ( (dynamic)result ).Content;

        Assert.IsEmpty( content );
        Assert.IsInstanceOf( typeof( System.Web.Http.Results.OkNegotiatedContentResult<IEnumerable<ListOfConstituencies>> ), result );
        _IConstituencyServiceMock.Verify( x => x.ListOfConstituencies(), Times.Once() );
    }
}
glaçages
la source
7
Je ne suis pas d'accord avec ça @gnat. Il ne s'agit pas nécessairement de constructions de langage mais du type de résultat renvoyé par un contrôleur. Bien que cela puisse se résumer en quelque sorte à la même chose lorsque vous n'avez pas de hiérarchie d'héritage, cela devient une bête tout à fait différente lorsque le contrôleur s'attend à ce que les ancêtres soient retournés, le contrôleur a renvoyé Person et maintenant Person est modifié pour descendre non pas d'Ancestor, mais PeopleAncestor ... Répond aussi aux raisons pour lesquelles tester une telle méthode peut être une bonne idée ...;) Les tests unitaires sont destinés à détecter les situations où un changement dans une chose c / casserait autre chose.
Marjan Venema
J'ai tendance à être d'accord, je ne passe généralement pas beaucoup de temps à tester les points d'entrée de l'application. C'est comme tester à l'unité une méthode principale d'une application console. n'a que très peu de sens pour moi.
Mvision

Réponses:

29

Leur point clé est ici:

Je saurais parfaitement si ce contrôleur a renvoyé le type voulu en exécutant la méthode dans un navigateur

Le test d'unité concerne l' automatisation des tests de non-régression de simples unités de code, pas que vous vous regardiez vous-même. Vous ne voulez pas faire vous-même les tests unitaires dans votre application.

EDIT: Ajout d'un commentaire @anotherdave:

Il s'agit de la facilité de mise à l'échelle. Tester un contrôleur dans un navigateur peut être OK; qu'en est-il de 10, 20, 50 contrôleurs? Vous écrirez le test une fois; vous devrez peut-être le mettre à jour lorsque vous changez le contrôleur, ce qui est une surcharge. Mais à quelle fréquence déployez-vous? Sûrement une vérification manuelle à chaque fois qu'il y a beaucoup plus de frais généraux que le test

Comme alternative à la réponse de @ Vladislav , les tests unitaires peuvent absolument être excessifs et vraiment indésirables. Si vous avez besoin de quelque chose de plus léger, vous pouvez effectuer des tests de non-régression de niveau supérieur en utilisant Selenium. Vous obtiendrez sûrement moins de couverture que les tests unitaires, mais vous pouvez obtenir une couverture raisonnable qui coûte beaucoup moins de temps à effectuer des tests unitaires et est plus flexible.

Autrement dit, si vous testez tout ce que vous avez, vous devez mettre à jour un ou plusieurs tests chaque fois que vous modifiez un élément simple.

Walfrat
la source
4
Pour ajouter également re: I would know perfectly well if this controller returned the wanted type by executing the method in a browser.- il s'agit de la facilité de mise à l'échelle. Tester un contrôleur dans un navigateur peut être OK; qu'en est-il de 10, 20, 50 contrôleurs? Vous écrirez le test une fois; vous devrez peut-être le mettre à jour lorsque vous changez le contrôleur, ce qui est une surcharge. Mais à quelle fréquence déployez- vous ? Sûrement une vérification manuelle à chaque fois qu'il y a beaucoup plus de frais généraux que le test.
anotherdave
"Le test unitaire concerne l'automatisation" - Correct, mais il en va de même pour les tests d'intégration (Selenium / Webdriver / etc.). Je ne pense pas que ce soit nécessairement si simple que les tests unitaires soient plus rapides à mettre en œuvre que les tests d'intégration. Cela dépend beaucoup de l'approche, mais si l'obtention d'un test unitaire efficace nécessite de simuler une douzaine de services et d'appels différents dans chacun d'eux, un test d'intégration peut être plus rapide à mettre en œuvre et plus simple à maintenir (bien que généralement beaucoup plus lent à exécuter, oui) . Le fait est que cela dépend beaucoup du contexte et de la complexité du code testé.
2016
@anotherdave commentaire ajouté
Walfrat
@aroth mon point de vue était le contraire, un test unitaire complet d'un code est quelque chose qui prend beaucoup de temps et rend le code très difficile à changer sans avoir un test unitaire à changer. Le test d'intégration est plus léger. Bien sûr, vous voudriez tester quelque chose de très complexe, mais ce n'est pas parce que vous avez testé cette partie, que vous devez tout tester à l'unité. Encore une fois, nous voyons des gens chercher la balle d'argent là où il n'existe pas.
Walfrat
24

Pourquoi voudriez-vous écrire des tests unitaires pour les contrôleurs?

Parce que sans connaître le contexte, vous ne pouvez pas dire avec certitude si vous devez tester ceci ou cela. Voici quelques raisons pour lesquelles vous voudrez peut-être tester les contrôleurs:

  • le contrôleur peut contenir une logique de câblage de service complexe, qui est sujette aux erreurs. Les services eux-mêmes peuvent fonctionner correctement, c'est le résultat que vous souhaitez tester et pour une raison quelconque, vous avez envisagé de ne pas introduire la couche d'orchestration dans votre application
  • vos contrôleurs contiennent TOUTE la logique commerciale de l'application et les contrôleurs sont en fait tout ce que vous POUVEZ tester (veuillez ne pas prétendre que toute votre vie vous avez travaillé avec des bases de code idéales, il y en a de telles, croyez-moi)
  • votre équipe est composée de 99% de génies et 1% de personnes moyennes et vous voulez garder ce 1% hors des bogues dans leur salaire
Vladislav Rastrusny
la source
2
J'ajouterais: "Vous ne pouvez pas prévoir qui à l'avenir va se débarrasser du projet, et les tests font partie du code auto-documenté"
Laiv
4
Au point médian, un projet qui a été créé sans test à l'esprit peut ne pas être testable autrement qu'un test de contrôleur sans maquette. Je travaille avec une équipe C # qui a exactement un tel projet à leur charge, ils écrivent donc des tests de contrôleur jusqu'à ce qu'ils puissent ajouter la structure nécessaire (interfaces, etc.) pour pouvoir effectuer des tests plus fins.
Wayne Conrad
1

Je suis entièrement d'accord avec l'OP.

Un test unitaire pour un contrôleur est inutile. Vous testez implicitement vos contrôleurs via des tests de régression (en utilisant Selenium par exemple).

Vous devez TDD tous les composants / objets que le contrôleur utilise et garder les contrôleurs aussi minces que possible. Ensuite, tout est correctement testé à l'unité. Ce dont vous voulez être certain, c'est que tout fonctionne bien ensemble lorsque vous effectuez des requêtes Web. Ce sont des tests de régression.

accolade
la source
Peut-être que oui, mais ce n'est pas une réponse à la question. En fait, c'est un argument contre l'utilisation de tests unitaires ici.
JᴀʏMᴇᴇ
Je pense avoir répondu à la question "croyez-vous qu'un test est nécessaire pour cela et pourquoi?"
winkbrace
Oui, je pense que @winkbrace et je partage les mêmes réflexions à ce sujet. Mais je crois aussi que c'est une discussion sur ce que vous devez tester unitaire et non. Je pense que les gens testent trop et les «mauvaises» choses. dans mon exemple, tester le contrôleur donne très peu de valeur car il est si mince et, espérons-le, comporte des tests entourant les services. Toutes les réponses ici sont significatives et ont de bons points, mais il n'est pas vraiment possible d'en marquer une comme une réponse correcte.
glaçages
La logique du contrôleur peut être testée à l'aide de tests d'intégration automatisés, séparés et distincts des tests unitaires pour les composants individuels.
KevBurnsJr
-1: Un test unitaire pour un contrôleur peut être inutile. Les contrôleurs concernent la transformation, mais parfois la transformation elle-même est complexe et un développeur peut vouloir la couvrir. Je pense également que les tests unitaires 1) visent en fin de compte à valider une implémentation, pas nécessairement à valider un comportement de haut niveau, et 2) sont censés être sacrément rapides . Les deux qualités rendent les tests unitaires beaucoup plus utiles pendant le temps de mise en œuvre; en d'autres termes, ils sont en fin de compte un outil de développeur, et juste accessoirement un moyen de valider la qualité des produits.
rsenna