简体   繁体   中英

RSpec stubs & mocks on related (belongs_to) relationships

I'm trying to get my head around RSpec's incredibly confusing, at least initially, syntax by trying to expand on the default specs that are generated with Rails 3 scaffolding...

I have associated models...very simply:

#clown.rb
class Clown < ActiveRecord::Base
  has_many :rabbits
end

#rabbit.rb
class Rabbit < ActiveRecord::Base
  belongs_to :clown
end

but I'm having trouble with rabbits_controller.spec.rb. In that the specs fail when I reference, say, clown. name in one of rabbit's views. the stupid simple app works as expected but the specs fail because I haven't stubbed (or mocked?) the clown to respond correctly from the rabbit (or at least that's what I think is happening)?!? How should I be adding a stub (or mocking the clown that the rabbit is associate to?).

existing:

   #rabbits.controller.spec.rb
    require 'spec_helper'

    describe RabbitsController do

      def mock_rabbit(stubs={})
        (@mock_rabbit ||= mock_model(Rabbit).as_null_object).tap do |rabbit|
          rabbit.stub(stubs) unless stubs.empty?
        end
      end

      describe "GET index" do
        it "assigns all rabbits as @rabbits" do
          Rabbit.stub(:all) { [mock_rabbit] }
          get :index
          assigns(:rabbits).should eq([mock_rabbit])
        end
      end

  ...

IMHO (and there are other points of view) this isn't a mocking or stubbing situation. Mocks and stubs are great for external dependencies (think web service), but this is internal to your application. What you want is something like factory_girl, which will let you create test data without the headaches of something like fixtures or trying to mock out every dependent relationship, which quickly becomes monotonous. factory_girl has great documentation, but briefly here's what your factories might look like:

Factory.define(:clown) do |f|
  f.rabbits{|c| [c.assocation(:rabbit)]}
  f.name "Pierrot"
end

Factory.define(:rabbit) do |f|
  f.association :clown
end

You'd then use them in your test like so:

describe RabbitsController do 
  describe "GET index" do 
    it "assigns rabbits" do
      @rabbit = Factory(:rabbit)
      get :index
      assigns[:rabbits].should == [@rabbit]      
    end
  end
end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM