[RUBY] Maquette et stub dans RSpec

Références Rails au quotidien - Introduction aux tests de rails avec RSpec https://leanpub.com/everydayrailsrspec-jp

Mock et stub

moquer

Un objet qui prétend être un véritable objet utilisé pour les tests. Aussi appelé test double. La maquette n'accède pas à la base de données, ce qui réduit le temps de test.

bout

Remplace les méthodes de l'objet et renvoie une valeur prédéterminée. Un stub est une méthode factice qui, lorsqu'elle est appelée, renvoie un résultat réel pour le test. Les stubs sont souvent utilisés pour remplacer la fonctionnalité par défaut d'une méthode. En particulier, les traitements utilisant une base de données ou un réseau sont ciblés.

J'écrirai réellement

La méthode name (combinaison de first_name + last_name) dans l'objet User est déléguée à l'objet Note et des attributs sont ajoutés.

Attributs utilisateur first_name et last_name ↓ Combinez first_name et last_name avec la méthode du nom de l'utilisateur ↓ Ajoutez la valeur combinée en tant que nom_utilisateur à l'attribut Note

Testez si cela fonctionne correctement.

Premier code.rb


it "Délégué obtenant le nom de l'utilisateur qui a créé la note" do
 user = FactoryBot.create(:user, first_name: "Fake", last_name: "User")
 note = Note.new(user: user)
 expect(note.user_name).to eq "Fake User"
end

Dans ce code L'objet utilisateur doit être enregistré dans la base de données et rendu persistant. À mesure que le nombre et la complexité augmentent, même s'il s'agit d'un test du modèle Note, seul le traitement inintéressant gonfle. Et dans le test du modèle Note, j'en sais trop sur l'implémentation du modèle User. Ce test ne s'intéresse pas au fait que le nom dans le modèle User a les attributs first_name et last_name. Tout ce que vous devez savoir, c'est que le modèle User renvoie le nom de la chaîne.

Sur cette base, une refactorisation sera effectuée.

Code refactoré.rb


it "Délégué obtenant le nom de l'utilisateur qui a créé la note" do
 #Remplacer l'objet utilisateur par double(moquer)
 user = double("user", name: "Fake User")
 note = Note.new
  #note.Un stub qui indique explicitement que l'utilisateur est appelé
 allow(note).to receive(:user).and_return(user)
 expect(note.user_name).to eq "Fake User"
end

Remplacement de la persistance de l'objet User par un simulacre. Puisque nous voulons que l'objet fictif ait une méthode, la clé et la valeur sont spécifiées après le deuxième argument. (La méthode du nom de l'utilisateur renvoie "Faux utilisateur") L'examen de cet objet révèle une classe nommée Double. Notez que cette maquette est un objet qui ne sait que renvoyer un nom. Bien sûr, si vous essayez de tester first_name comme indiqué ci-dessous, vous obtiendrez une erreur car vous ne pouvez pas renvoyer de valeur.

expect(note.user.first_name).to eq "Fake"

Ensuite, regardons le stub. Le stub est créé avec allow. (Utilisez allow (obj) .to receive (: method) si l'objet récepteur n'est pas un objet fictif mais un objet existant) La méthode d'écriture est illustrée ci-dessous.

#and_La valeur de retour de la méthode est spécifiée par return.
allow(obj).to receive(:method).and_return(true)

Le code refactorisé nous dit d'appeler note.user quelque part dans le test.

allow(note).to receive(:user).and_return(user)

Quand user.name est réellement appelé, la valeur de note.user_id est utilisée pour rechercher l'utilisateur approprié dans la base de données, et au lieu de renvoyer l'utilisateur trouvé, un double utilisateur de test est renvoyé.

Cliquez ici pour un article très facile à comprendre Developers.IO https://dev.classmethod.jp/articles/rspec-recipe/ Introduction à RSpec utilisable, partie 3 "Comment écrire un test en utilisant une simulation compréhensible à partir de zéro" https://qiita.com/jnchito/items/640f17e124ab263a54dd

Vous n'avez plus besoin d'enregistrer l'objet User dans la base de données et de le rendre persistant. Et pour le test du modèle Note, j'ai pu le refactoriser avec un intérêt minimal pour le modèle User. Cependant, il y a encore des problèmes.

Test double avec fonction de vérification

Le double test de RSpec ne vérifie pas que l'objet qu'il essaie de remplacer a une méthode qu'il souhaite stub. En d'autres termes, la méthode appelée par le stub ne sera pas définie, mais le test passera. Lors de l'utilisation d'un test double autant que possible, il est souhaitable d'utiliser un test double avec une fonction de vérification. Par conséquent, passez à un double vérifié avec une fonction de vérification.

Code modifié pour doubler avec vérification.rb


it "Délégué obtenant le nom de l'utilisateur qui a créé la note" do
 #instance_Changer pour doubler. Changer la première lettre de l'utilisateur en majuscule
 user = instance_double("User", name: "Fake User")
 note = Note.new
 allow(note).to receive(:user).and_return(user)
 expect(note.user_name).to eq "Fake User"
end

C'est fondamentalement la même chose que double, sauf que vous obtenez une erreur lorsque vous stub une méthode d'instance non définie. Par conséquent, il est possible d'écrire un test tout en confirmant que la méthode existe.

Merci de rester avec nous jusqu'à la fin. Si vous avez des suggestions ou des conseils, je vous serais reconnaissant de bien vouloir commenter.

Recommended Posts

Maquette et stub dans RSpec
Mock et stub avec minitest (utilisez RR, WebMock, MiniTest :: Mock)
[Rails] Comment définir des macros dans Rspec et standardiser le traitement
Mock et espionner PowerMock
Méthodes statiques simulées dans Mockito 3.4
[Wire Mock] Je souhaite configurer un serveur stub / simulé en Java et effectuer des tests E2E.
Si vous souhaitez simuler une méthode dans RSpec, vous devez utiliser la méthode allow pour mock et la méthode singleton.
Activer jQuery et Bootstrap dans Rails 6 (Rails 6)
Exemple d'encodage et de décodage en Java
Essayez d'exécuter ruby-net-nntp et tmail en 2020
Différence approximative entre RSpec et minitest
CGI en C et Dart: Introduction (1)
Classe StringBuffer et StringBuilder en Java
Ecrire des clés et des valeurs dans Ruby
Supprimez les "actifs" et les "turbolinks" dans "Rails6".
Fonction CRUD et MVC dans Rails
Comprendre equals et hashCode en Java
Copier et coller le test avec RSpec
Bonjour tout le monde en Java et Gradle
Comment tester une méthode privée et la simuler partiellement en Java