Comment dire “any_instance” “should_receive” un nombre quelconque de fois dans RSpec

J’ai un contrôleur d’import dans les rails qui importe plusieurs fichiers CSV avec plusieurs enregistrements dans ma firebase database. Je voudrais tester dans RSpec si les enregistrements sont réellement enregistrés en utilisant RSpec:

.any_instance.should_receive(:save).at_least(:once) 

Cependant, je reçois l’erreur en disant:

 The message 'save' was received by  but has already been received by  

Un exemple artificiel du contrôleur:

 rows = CSV.parse(uploaded_file.tempfile, col_sep: "|") ActiveRecord::Base.transaction do rows.each do |row| mutation = Mutation.new row.each_with_index do |value, index| Mutation.send("#{atsortingbute_order[index]}=", value) end mutation.save end 

Est-il possible de tester cela avec RSpec ou existe-t-il une solution de contournement?

Il y a une nouvelle syntaxe pour ceci:

 expect_any_instance_of(Model).to receive(:save).at_least(:once) 

Voici une meilleure réponse qui évite de devoir remplacer la nouvelle méthode:

 save_count = 0 .any_instance.stub(:save) do |arg| # The evaluation context is the rspec group instance, # arg are the arguments to the function. I can't see a # way to get the actual  instance :( save_count+=1 end .... run the test here ... save_count.should > 0 

Il semblerait que la méthode stub puisse être associée à n’importe quelle instance sans la contrainte, et le bloc do peut faire en sorte que le décompte que vous pouvez vérifier soit appelé le bon nombre de fois.

Update – la nouvelle version de rspec requirejs cette syntaxe:

 save_count = 0 allow_any_instance_of(Model).to receive(:save) do |arg| # The evaluation context is the rspec group instance, # arg are the arguments to the function. I can't see a # way to get the actual  instance :( save_count+=1 end .... run the test here ... save_count.should > 0 

J’ai finalement réussi à faire un test qui fonctionne pour moi:

  mutation = FactoryGirl.build(:mutation) Mutation.stub(:new).and_return(mutation) mutation.should_receive(:save).at_least(:once) 

La méthode de remplacement renvoie une seule instance qui reçoit la méthode d’enregistrement plusieurs fois. Comme il s’agit d’une instance unique, je peux supprimer la méthode any_instance et utiliser la méthode at_least normalement.

Stub comme ça

 User.stub(:save) # Could be any class method in any class User.any_instance.stub(:save) { |*args| User.save(*args) } 

Alors attendez comme ceci:

 # User.any_instance.should_receive(:save).at_least(:once) User.should_receive(:save).at_least(:once) 

Ceci est une simplification de cet élément , pour utiliser any_instance , puisque vous n’avez pas besoin de proxy pour la méthode d’origine. Reportez-vous à cette liste pour d’autres utilisations.

C’est l’exemple de Rob utilisant RSpec 3.3, qui ne supporte plus Foo.any_instance . J’ai trouvé cela utile en boucle dans la création d’objects

 # code (simplified version) array_of_hashes.each { |hash| Model.new(hash).write! } # spec it "calls write! for each instance of Model" do call_count = 0 allow_any_instance_of(Model).to receive(:write!) { call_count += 1 } response.process # run the test expect(call_count).to eq(2) end 

Mon cas était un peu différent, mais je me suis retrouvé à cette question à penser à laisser tomber ma réponse ici aussi. Dans mon cas, je voulais supprimer n’importe quelle instance d’une classe donnée. J’ai eu la même erreur lorsque j’ai utilisé expect_any_instance_of(Model).to . Quand je l’ai changé pour allow_any_instance_of(Model).to , mon problème a été résolu.

Consultez la documentation pour plus d’informations: https://github.com/rspec/rspec-mocks#settings-mocks-or-stubs-on-any-instance-of-a-class