Ich habe einen Import-Controller in Rails, der mehrere CSV-Dateien mit mehreren Datensätzen in meine Datenbank importiert. Ich möchte in RSpec testen, ob die Datensätze tatsächlich mithilfe von RSpec gespeichert werden:
<Model>.any_instance.should_receive(:save).at_least(:once)
Ich erhalte jedoch die Fehlermeldung:
The message 'save' was received by <model instance> but has already been received by <another model instance>
Ein erfundenes Beispiel für die Steuerung:
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("#{attribute_order[index]}=", value)
end
mutation.save
end
Ist es möglich, dies mit RSpec zu testen, oder gibt es eine Problemumgehung?
Antworten:
Hierfür gibt es eine neue Syntax:
expect_any_instance_of(Model).to receive(:save).at_least(:once)
quelle
expect_any_instance_of
. Hier ist ein Link zum Dokument .Hier ist eine bessere Antwort, bei der vermieden wird, dass Folgendes überschrieben werden muss: Neue Methode:
save_count = 0 <Model>.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 <Model> instance :( save_count+=1 end .... run the test here ... save_count.should > 0
Es scheint, dass die Stub-Methode ohne die Einschränkung an jede Instanz angehängt werden kann und der do-Block eine Zählung durchführen kann, die Sie überprüfen können, um sicherzustellen, dass sie die richtige Anzahl von Malen aufgerufen wurde.
Update - Neue rspec-Version erfordert diese Syntax:
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 <Model> instance :( save_count+=1 end .... run the test here ... save_count.should > 0
quelle
Ich habe es endlich geschafft, einen Test zu machen, der für mich funktioniert:
mutation = FactoryGirl.build(:mutation) Mutation.stub(:new).and_return(mutation) mutation.should_receive(:save).at_least(:once)
Die Stub-Methode gibt eine einzelne Instanz zurück, die die Speichermethode mehrmals empfängt. Da es sich um eine einzelne Instanz handelt, kann ich die
any_instance
Methode löschen undat_least
normal verwenden.quelle
Stub so
User.stub(:save) # Could be any class method in any class User.any_instance.stub(:save) { |*args| User.save(*args) }
Dann erwarten Sie so:
# User.any_instance.should_receive(:save).at_least(:once) User.should_receive(:save).at_least(:once)
Dies ist eine Vereinfachung dieses Kerns ,
any_instance
da Sie keinen Proxy für die ursprüngliche Methode benötigen. Beziehen Sie sich für andere Zwecke auf dieses Wesentliche.quelle
allow
undallow_any_instance_of
anstelle vonstub
undany_instance.stub
da die ersteren jetzt veraltet sind (siehe: github.com/rspec/… )Dies ist Robs Beispiel mit RSpec 3.3, das nicht mehr unterstützt wird
Foo.any_instance
. Ich fand dies nützlich, wenn in einer Schleife Objekte erstellt wurden# 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
quelle
Mein Fall war ein bisschen anders, aber ich kam zu dieser Frage, um meine Antwort auch hier fallen zu lassen. In meinem Fall wollte ich jede Instanz einer bestimmten Klasse stubben. Ich habe den gleichen Fehler bekommen, als ich verwendet habe
expect_any_instance_of(Model).to
. Als ich es änderte,allow_any_instance_of(Model).to
war mein Problem gelöst.Weitere Hintergrundinformationen finden Sie in der Dokumentation: https://github.com/rspec/rspec-mocks#settings-mocks-or-stubs-on-any-instance-of-a-class
quelle
expect_any_instance_of(Widget).to receive(:name).twice
ist nicht klar, ob jede bestimmte Instanz vorhanden ist wird voraussichtlichname
zweimal empfangen , oder wenn zwei insgesamt empfangen werden. (Es ist das erstere.) "Sie können versuchen, die Anzahl der
new
in der Klasse zu zählen. Das testet eigentlich nicht die Anzahl dersave
s, kann aber ausreichenexpect(Mutation).to receive(:new).at_least(:once)
Wenn es die einzige Erwartung gibt, wie oft es gespeichert wurde. Dann möchten Sie wahrscheinlich
spy()
anstelle der voll funktionsfähigen Fabrik verwenden, wie in derHarm de Wit
eigenen Antwortallow(Mutation).to receive(:new).and_return(spy) ... expect(Mutation.new).to have_received(:save).at_least(:once)
quelle