104 votes

Est-ce que la méthode stubbed de RSpec peut renvoyer des valeurs différentes dans une séquence ?

Je dispose d'un modèle Family avec une méthode location qui fusionne les sorties de location d'autres objets, les Membres. (Les Membres sont associés aux familles, mais ce n'est pas important ici.)

Par exemple, étant donné

  • member_1 a location == 'San Diego (en voyage, retour le 15 mai)'
  • member_2 a location == 'San Diego'

Family.location pourrait retourner 'San Diego (membre_1 en voyage, retour le 15 mai)' Les détails ne sont pas importants.

Pour simplifier le test de Family.location, je veux simuler Member.location. Cependant, j'ai besoin qu'il renvoie deux valeurs différentes (spécifiées) comme dans l'exemple ci-dessus. Idéalement, celles-ci seraient basées sur un attribut de membre, mais simplement renvoyer des valeurs différentes dans une séquence serait acceptable. Y a-t-il un moyen de le faire dans RSpec?

Il est possible de remplacer la méthode Member.location dans chaque exemple de test, comme

it "lorsque la résidence est la même" do 
  class Member
    def location
      return {:residence=>'Domicile', :travail=>'son_travail'} if self.male?
      return {:residence=>'Domicile', :travail=>'son_travail'}
    end
  end
  @family.location[:residence].should == 'Domicile'
end

mais je doute que ce soit une bonne pratique. Dans tous les cas, lorsque RSpec exécute une série d'exemples, il ne restaure pas la classe d'origine, de sorte que ce type de substitution "empoisonne" les exemples suivants.

Alors, y a-t-il un moyen d'avoir une méthode simulée renvoyant des valeurs différentes et spécifiées à chaque appel?

0voto

CamiEQ Points 575

J'avais le problème que j'avais plusieurs appels à une méthode et pas toujours dans le même ordre. Dans ce cas, je recommanderais d'utiliser .with, pour distinguer les instances, en utilisant les arguments de la méthode.

Par exemple, voici ce que pourrait être votre valeur de retour "par défaut" :

allow(@family).to receive(:location).and_return('son_travail')

mais ensuite, si la méthode location reçoit un argument comme "homme", vous pouvez ajouter :

allow(@family).to receive(:location).with("homme").and_return('son_travail')

Il existe de nombreux types d'arguments de correspondance différents qui peuvent être utilisés avec .with:

https://relishapp.com/rspec/rspec-mocks/v/3-2/docs/setting-constraints/matching-arguments

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