Search code examples
ruby-on-railscachingrspecsweeper

Testing a sweeper with RSpec in Rails


I want to make sure my sweeper is being called as appropriate so I tried adding something like this:

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

But I just get:

<FooSweeper (class)> expected :after_save with (...) once, but received it 0 times

I've tried turning on caching in the test config but that didn't make any difference.


Solution

  • As you already mentioned caching has to be enabled in the environment for this to work. If it's disabled then my example below will fail. It's probably a good idea to temporarily enable this at runtime for your caching specs.

    'after_save' is an instance method. You setup an expectation for a class method, which is why it's failing.

    The following is the best way I've found to set this expectation:

    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
    

    The problem is that Foo's observers (sweepers are a subclass of observers) are set when Rails boots up, so we have to insert our sweeper mock directly into the model with 'instance_variable_set'.