On 21 Oct 2009, at 06:40, Christoph ---- wrote:
Hi
I am new to Rspec and try to mock my controller that looks like

def create
   @friendship = current_user.friendships.build(:friend_id =>
params[:friend_id])
   if @friendship.save
     flash[:notice] = "Added friend."
     render :text => flash[:notice]
   else
     flash[:error] = "Error occurred when adding friend."
     render :text => flash[:notice]
   end
 end

how can I mock
current_user.friendships.build ?

I tried

before(:each) do
   @friend_ship = mock_model(Friendship, :friend_id => 1947284801,
:user_id => 134245544)
controller.stub!(:current_user).should_receive ('friendships').and_return(@friend_ship)
end

but get
You have a nil object when you didn't expect it! The error occurred
while evaluating nil.friendship

Hi Christoph ----

You're making three mistakes:
(1) confusing the collection with the model (friendships vs friendship)
(2) using the wrong stub syntax (I think - I don't actually chain calls after `stub` together like that)
(3) putting an expectation in the `before` block

If you *really* want to do it this way, you'd have to write something along these lines:

  describe User do
    before(:each) do
      @friendship = mock_model(
        Friendship, :friend_id => 1947284801, :user_id => 134245544
      )
      # Issue (1)
@friendships = mock("ActiveRecord collection", :build => @friendship)

      # Issue (1)
      @user = mock_model(User, :friendships => @friendships)

      # Issue (2)
      controller.stub!(:current_user).and_return(@user)
    end

    it "should build a user" do
      # Issue (3)
@friendships.should_receive(:build).with(:friend_id => YOUR_EXPECTED_FRIEND_ID)
      # Put whatever rspec-rails provides to invoke the action here
    end
  end

(disclaimer - not run)

However - this is a fragile solution because it makes assumptions about the ActiveRecord magic in User (it's a violation of Law of Demeter[1], which I believe you have to pay extra attention to with ActiveRecord code). It is more stable to write a method User#build_friendship that takes the appropriate args - you can then spec the behaviour in the model layer.

Sorry I can't go into more detail about the above issues - I'm writing this over a quick coffee in the station before I go to the office.

HTH

Ashley

[1] http://en.wikipedia.org/wiki/Law_of_Demeter

--
http://www.patchspace.co.uk/
http://www.linkedin.com/in/ashleymoran
http://aviewfromafar.net/







_______________________________________________
rspec-users mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/rspec-users

Reply via email to