Как сказать "любой экземпляр ""должен получить" любое количество раз в RSpec
у меня есть контроллер импорта в rails, который импортирует несколько файлов csv с несколькими записями в мою базу данных. Я хотел бы проверить в RSpec, если записи фактически сохраняются с помощью RSpec:
<Model>.any_instance.should_receive(:save).at_least(:once)
однако я получаю сообщение об ошибке:
The message 'save' was received by <model instance> but has already been received by <another model instance>
надуманный пример контроллера:
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
можно ли проверить это с помощью RSpec или есть ли обходной путь?
6 ответов:
вот лучший ответ, который позволяет избежать необходимости переопределять: новый метод:
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
Кажется, что метод заглушки может быть присоединен к любому экземпляру без ограничения, и блок do может сделать подсчет, который вы можете проверить, чтобы утверждать, что он был вызван правильное количество раз.
обновление-для новой версии rspec требуется следующий синтаксис:
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
я, наконец, удалось сделать тест, который работает для меня:
mutation = FactoryGirl.build(:mutation) Mutation.stub(:new).and_return(mutation) mutation.should_receive(:save).at_least(:once)
метод stub возвращает один экземпляр, который получает метод save несколько раз. Потому что это единственный экземпляр, который я могу отбросить
any_instance
метод и использоватьat_least
обычно метод.
окурок вот так
User.stub(:save) # Could be any class method in any class User.any_instance.stub(:save) { |*args| User.save(*args) }
тогда ожидайте вот так:
# User.any_instance.should_receive(:save).at_least(:once) User.should_receive(:save).at_least(:once)
это упрощение в этом суть использовать
any_instance
, так как вам не нужно прокси к исходному методу. Обратитесь к этой сути для других целей.
это пример Роба с использованием RSpec 3.3, который больше не поддерживает
Foo.any_instance
. Я нашел это полезным, когда в цикле создания объектов# 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
мой случай был немного другим, но я в конечном итоге на этот вопрос решил бросить свой ответ здесь тоже. В моем случае я хотел заглушить любой экземпляр данного класса. Я получил ту же ошибку, когда я использовал
expect_any_instance_of(Model).to
. Когда я изменил его на моя проблема.ознакомьтесь с документацией для получения дополнительной информации: https://github.com/rspec/rspec-mocks#settings-mocks-or-stubs-on-any-instance-of-a-class