Test d'une balayeuse avec RSpec dans Rails
-
23-08-2019 - |
Question
Je veux vous assurer que mon balai est appelé selon le cas, donc j'ai essayé d'ajouter quelque chose comme ceci:
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
Mais je viens d'obtenir:
<FooSweeper (class)> expected :after_save with (...) once, but received it 0 times
J'ai essayé d'allumer la mise en cache dans la configuration de test, mais qui ne fait aucune différence.
La solution
Comme vous l'avez déjà mentionné la mise en cache doit être activé dans l'environnement pour que cela fonctionne. Si elle est désactivée alors mon exemple ci-dessous échouera. Il est probablement une bonne idée de permettre temporairement ce lors de l'exécution de vos spécifications de mise en cache.
'after_save' est une méthode d'instance. Vous configurer une attente pour une méthode de classe, ce qui explique pourquoi il est défaillant.
Ce qui suit est la meilleure façon que je l'ai trouvé pour régler cette attente:
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
Le problème est que les observateurs de Foo (les balayeurs sont une sous-classe d'observateurs) sont fixés lors du démarrage Rails, donc nous devons insérer notre maquette de balayeuse directement dans le modèle avec « instance_variable_set ».
Autres conseils
Sweepers sont singletons et sont instanciés au début du test rspec. A ce titre, vous pouvez y accéder via MySweeperClass.instance (). Cela a fonctionné pour moi (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
En supposant que vous avez:
- une classe
FooSweeper
- une classe
Foo
avec un attributbar
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