I have two models: Student has_many=>:grad_surveys and GradSurvey belongs_to=>:student I am testing the GradSurveysController#update method with it "should only allow update if the correct token is presented" do @params = {:id=>"1", :token=>"ab56e1b47", :survey=>{}} @mock_grad_survey = mock_model(GradSurvey) GradSurvey.should_receive(:accepts_as_authorized).with(@params [:id], at params[:token]).and_return(@mock_grad_survey) put :update, @params response.should render_template(:update) end Inside the GradSurvey#accepts_as_authorized method is called the GradSurvey#student method. The test above fails with the message: Mock ''GradSurvey_1034'' received unexpected message :student with (no args) However I can make the test pass by adding the :student method to the @mock_grad_survey object, so @mock_grad_survey = mock_model(GradSurvey, :student=>mock_model (Student)) Why is it necessary for me to explicitly add the #student method to the mock GradSurvey model, it seems to me that it should come for free as part of the defined association, no? What am I not understanding here? thanks in advance for any light you are able to shed
David Chelimsky
2009-Aug-04 16:34 UTC
[rspec-users] stubbing association methods in controller spec
On Thu, Jul 30, 2009 at 6:13 PM, norm<codehacker at comcast.net> wrote:> I have two models: > ?Student has_many=>:grad_surveys > ? ?and > ?GradSurvey belongs_to=>:student > > I am testing the GradSurveysController#update method with > > ?it "should only allow update if the correct token is presented" do > ? ?@params = {:id=>"1", :token=>"ab56e1b47", :survey=>{}} > ? ?@mock_grad_survey = mock_model(GradSurvey) > ? ?GradSurvey.should_receive(:accepts_as_authorized).with(@params > [:id], at params[:token]).and_return(@mock_grad_survey) > ? ?put :update, @params > ? ?response.should render_template(:update) > ?end > > Inside the GradSurvey#accepts_as_authorized method is called the > GradSurvey#student method. The test above fails with the message: > ? ? ? ? Mock ''GradSurvey_1034'' received unexpected message :student > with (no args) > > However I can make the test pass by adding the :student method to the > @mock_grad_survey object, so > ? ? ?@mock_grad_survey = mock_model(GradSurvey, :student=>mock_model > (Student)) > > Why is it necessary for me to explicitly add the #student method to > the mock GradSurvey model, it seems to me that it should come for free > as part of the defined association, no? What am I not understanding > here? > > thanks in advance for any light you are able to shedmock_model creates a test double - it''s not a real GradSurvey. Try using stub_model instead: @grad_survey = stub_model(GradSurvey) This uses a real model instance that is modified to not talk to the database. HTH, David