Testando um varredor com RSpec em Rails
-
23-08-2019 - |
Pergunta
Eu quero ter certeza que meu varredor está sendo chamado como apropriado, então eu tentei adicionar algo como isto:
it "should clear the cache" do
@foo = Foo.new(@create_params)
Foo.should_receive(:new).with(@create_params).and_return(@foo)
FooSweeper.should_receive(:after_save).with(@foo)
post :create, @create_params
end
Mas eu fico:
<FooSweeper (class)> expected :after_save with (...) once, but received it 0 times
Eu tentei ligar cache na configuração de teste, mas isso não faz qualquer diferença.
Solução
Como você já caching mencionado tem que ser ativado no ambiente para que isso funcione. Se for desativado, em seguida, o meu exemplo a seguir irá falhar. É provavelmente uma boa idéia para activar esta temporariamente em tempo de execução para suas especificações de armazenamento em cache.
'after_save' é um método de instância. Você pode configurar uma expectativa para um método de classe, que é por isso que está falhando.
A seguir é a melhor maneira que eu encontrei para definir essa expectativa:
it "should clear the cache" do
@foo = Foo.new(@create_params)
Foo.should_receive(:new).with(@create_params).and_return(@foo)
foo_sweeper = mock('FooSweeper')
foo_sweeper.stub!(:update)
foo_sweeper.should_receive(:update).with(:after_save, @foo)
Foo.instance_variable_set(:@observer_peers, [foo_sweeper])
post :create, @create_params
end
O problema é que os observadores do Foo (varredores são uma subclasse de observadores) são definidos quando o Rails botas para cima, por isso temos de inserir o nosso simulada varredor diretamente para o modelo com 'instance_variable_set'.
Outras dicas
Varredores são Singletons e são instanciado no início do teste rspec. Como tal, você pode obtê-lo via MySweeperClass.instance (). Isso funcionou para mim (Rails 3.2):
require 'spec_helper'
describe WidgetSweeper do
it 'should work on create' do
user1 = FactoryGirl.create(:user)
sweeper = WidgetSweeper.instance
sweeper.should_receive :after_save
user1.widgets.create thingie: Faker::Lorem.words.join("")
end
end
Assumindo que você tem:
- uma classe
FooSweeper
- uma classe
Foo
com um atributobar
foo_sweeper_spec.rb
:
require 'spec_helper'
describe FooSweeper do
describe "expiring the foo cache" do
let(:foo) { FactoryGirl.create(:foo) }
let(:sweeper) { FooSweeper.instance }
it "is expired when a foo is updated" do
sweeper.should_receive(:after_update)
foo.update_attribute(:bar, "Test")
end
end
end