78 votes

Comment doit-on unité de test une .NET MVC contrôleur?

Je suis à la recherche pour obtenir des conseils de l'efficacité de l'unité de test de .NET mvc contrôleurs.

Là où je travaille, beaucoup de ces tests utilisent moq pour se moquer de la couche de données, et d'affirmer que certaines données de la couche des méthodes sont appelées. Cela ne semble pas utile pour moi, puisqu'il est essentiellement vérifie que la mise en œuvre n'a pas changé plutôt que de tester l'API.

J'ai aussi lu des articles de recommander des choses comme vérifier que le type de modèle de vue retourné est correct. Je peux voir que la fourniture d'une certaine valeur, mais seul, il ne semble pas le mérite de l'effort d'écriture, de nombreuses lignes de moqueries (code de notre application, modèle de données est très vaste et très complexe).

Quelqu'un peut-il suggérer quelques de meilleures approches pour contrôleur de tests unitaires ou d'expliquer pourquoi les approches ci-dessus sont valables et utiles?

Merci!

58voto

danludwig Points 19213

Un contrôleur de test unitaire doit tester le code des algorithmes dans vos méthodes d'action, pas dans votre couche de données. C'est une des raisons pour se moquer de ceux des services de données. Le contrôleur s'attend à recevoir certaines valeurs à partir des référentiels / services / etc, et à agir différemment lorsqu'il reçoit des informations différentes d'eux.

Vous écrire des tests unitaires pour affirmer le contrôleur se comporte de façon très spécifique dans des scénarios très spécifiques ou les circonstances. Votre couche de données est une partie de l'application qui fournit les circonstances de l'action de contrôleur de méthodes. Affirmer qu'une méthode de service a été appelé par le contrôleur est précieuse, car vous pouvez être certain que le contrôleur reçoit les informations en provenance d'un autre endroit.

Vérifier le type de la viewmodel retourné est précieuse, car, si le mauvais type de viewmodel est retourné, MVC va lancer une exception d'exécution. Vous pouvez empêcher que cela se passe dans la production par l'exécution d'un test unitaire. Si le test échoue, la vue peut lancer une exception dans la production.

Les tests unitaires peuvent être utiles parce qu'ils font de refactoring beaucoup plus facile. Vous pouvez changer la mise en œuvre, et d'affirmer que le comportement est toujours le même en vous assurant que tous les tests unitaires passent.

Réponse au commentaire n ° 1

Si la modification de la mise en œuvre d'une méthode à l'essai des appels pour que la modification ou la suppression d'une couche inférieure se moquaient de méthode, l'appareil d'essai doit également changer. Toutefois, cela ne devrait pas arriver aussi souvent que vous le pensez.

Le typique rouge-vert-refactoriser le flux des appels pour l'écriture des tests unitaires avant d' écrire les méthodes de test. (Cela signifie que pour une courte période de temps, votre test de code ne compile pas, et c'est pourquoi de nombreux jeunes et inexpérimentés, les développeurs ont de la difficulté à adopter rouge vert refactoriser.)

Si vous écrivez des tests unitaires d'abord, vous arriverez à un point où vous savez que le contrôleur a besoin d'obtenir des informations à partir d'une couche inférieure. Comment pouvez-vous être certain qu'il essaie d'obtenir cette information? En se moquant de la couche inférieure de la méthode qui fournit de l'information, et en affirmant que la couche inférieure de la méthode est invoquée par le contrôleur.

J'ai peut-être me suis mal exprimée quand j'ai utilisé le terme "modification de la mise en œuvre." Lorsque l'action d'un controller la méthode et les correspondants de l'unité de test doit être modifié pour modifier ou supprimer un moqué de la méthode, vous êtes vraiment changer le comportement du contrôleur. Refactoring, par définition, implique la modification de la mise en œuvre sans modifier le comportement global et les résultats attendus.

Rouge-vert-refactor est une démarche d'Assurance Qualité qui aide à prévenir les bogues et défauts dans le code, avant d'apparaître. Généralement, les développeurs de changement de mise en œuvre pour supprimer les bugs après leur apparition. Donc, pour résumer, les cas vous êtes inquiet au sujet ne devrait pas se produire aussi souvent que vous le pensez.

30voto

Darin Dimitrov Points 528142

Vous devez d'abord mettre les manettes sur un régime alimentaire. Ensuite, vous pouvez avoir du plaisir de l'unité de l'épreuve. Si elles sont grosses et que vous avez en peluche toute votre logique métier à l'intérieur d'eux, je suis d'accord que vous allez passer votre vie se moquant de choses dans vos tests unitaires et de se plaindre que c'est une perte de temps.

Quand vous parlez d'une logique complexe, cela ne signifie pas nécessairement que cette logique ne peut pas être séparés dans des couches différentes et chaque méthode a été testé avec succès dans l'isolement.

10voto

unovis Points 71

Le point d'un test unitaire est de tester le comportement d'une méthode dans l'isolement, basé sur un ensemble de conditions. Vous définissez les conditions de l'essai à l'aide des objets fantaisie, et de faire valoir la méthode du comportement en regardant comment il interagit avec d'autres code autour de lui -- par la vérification externe des méthodes qu'il tente de l'appeler, mais surtout par la vérification de la valeur qu'elle renvoie vu les conditions.

Ainsi, dans le cas de méthodes de Contrôleur, qui de retour ActionResults, il est très utile d'examiner la valeur de retour de la ActionResult.

Jetez un oeil à la section "Créer des Tests Unitaires pour les Contrôleurs ici pour quelques exemples très clairs de cas à l'aide de Moq.

Voici un bel échantillon de cette page les tests d'une vue est renvoyé lorsque le Contrôleur tente de créer un enregistrement de contact et il échoue.

[TestMethod]
public void CreateInvalidContact()
{
    // Arrange
    var contact = new Contact();
    _service.Expect(s => s.CreateContact(contact)).Returns(false);
    var controller = new ContactController(_service.Object);

    // Act
    var result = (ViewResult)controller.Create(contact);

    // Assert
    Assert.AreEqual("Create", result.ViewName);
}

7voto

ulu Points 1213

Je ne vois pas beaucoup de point dans les tests unitaires, le contrôleur, car il est généralement juste un morceau de code qui se connecte à d'autres pièces. Les tests unitaires, il comprend généralement beaucoup de moqueries et vérifie juste que les autres services sont correctement connectés. Le test lui-même est une réflexion de la mise en œuvre du code.

Je préfère les tests d'intégration -- je commence pas avec un béton de contrôleur, mais avec une Url, et vérifiez que le retour de Modèle a les valeurs correctes. Avec l'aide de Ivonna, le test pourrait ressembler à:

var response = new TestSession().Get("/Users/List");
Assert.IsInstanceOf<UserListModel>(response.Model);

var model = (UserListModel) response.Model;
Assert.AreEqual(1, model.Users.Count);

Je peux moquer de la base de données access, mais je préfère une approche différente: le programme d'installation en mémoire une instance de SQLite, et de le recréer à chaque nouveau test, en collaboration avec les données requises. Il rend mes tests assez vite, mais au lieu de compliqué moqueur, je leur fais de claire, par exemple, il suffit de créer et d'enregistrer un Utilisateur par exemple, plutôt que de se moquer de l' UserService (ce qui pourrait être un détail de l'implémentation).

1voto

Joachim Isaksson Points 85969

Généralement, lorsqu'on parle de tests unitaires, vous êtes des tests d'une procédure individuelle ou d'une méthode, et non pas l'ensemble d'un système, tout en essayant d'éliminer toutes les dépendances externes.

En d'autres termes, lors du test de la manette, vous écrivez des tests de la méthode par méthode, et vous ne devriez pas besoin d'avoir la vue ou le modèle chargé, ceux sont les pièces que vous devrait "se moquer de". Vous pouvez ensuite modifier l'on se moque de retourner des valeurs ou des erreurs qui sont difficiles à reproduire dans d'autres essais.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X