Checking that a controller created a separate model object

Hi everyone, RSpec newbie here. I’m looking forward to interacting with
community as I learn more about TDD, RSpec, Rails, and… TDD through
in Rails.

Having watched the Peepcode screencasts and read a lot of documentation,
trying to write my first comprehensive applications using TDD from the
ground up. I’m stuck writing a test for my controller, though.

This application is your basic crappy social network. There are three
relevant models in play right now: User, Group, and Membership. User
Group have :has_many relationships with each other :through Membership;
Membership, in addition to having a user_id and a group_id, also has a
column called “rank”, to which I write in either “officer” or “member”
as a

Group also defines the following relationships just for convenience:

has_many :memberships
has_many :officers, :through => :memberships, :source => :user,
:conditions => “rank = ‘officer’”
has_many :members, :through => :memberships, :source => :user,
=> “rank = ‘member’”

I’m trying to test the CREATE functionality in my Group controller.
Unfortunately, this test is not working.

  it "should make the creating user an officer" do
    Group.stub!(:new).and_return(mock_group(:save => true))
    post :create, :group => {}
    assigns[:group].should have(1).officer

The error message:
Mock ‘Group_1008’ received unexpected message :officer with (no args)

If I understand this correctly, I am getting the error because
assigns[:group] isn’t really an ActiveRecord object, just a mock, and I
guess the relationships don’t carry over? If this is the case, what’s
right way to test it, assuming that a Membership really is being created
my controller’s create function?


On 2008-10-12, at 22:33, O. Frabjous-Dey wrote:

three relevant models in play right now: User, Group, and
has_many :members, :through => :memberships, :source


Hi O. The Group that you’re creating is a Mock. Thus, it doesn’t have
any of the methods (Eg: #officer) that a real Group has. Since
#officer hasn’t been stubbed out on the mock Group, the error occurs.

As for how to spec that the relationships are being setup correctly,
can you provide the code for the Group’s “new” action?


On 2008-10-12, at 23:49, O. Frabjous-Dey wrote:

flash[:notice] = ‘Group was successfully created.’

Hi again, O. In your spec, you’re stubbing Group#new and returning a
mock. As a result, the “create” action uses that mock when creating
the Membership object. I’ve never specced relationships, so I’m not
sure what to suggest. Hopefully someone else can give some advice.


BTW, that last email of yours was sent directly to me, rather than to
the mailing list. Let’s keep all of the messages on the list.

On Mon, Oct 13, 2008 at 1:47 PM, Nick H. [email protected]


respond_to do |format|

BTW, that last email of yours was sent directly to me, rather than to the
mailing list. Let’s keep all of the messages on the list.

Whoops! Sorry this was sent straight to you, Nick. I should have hit
Reply-all. (Also that the subject line isn’t formatted correctly; I
mistakenly thought that the listserv software would prepend
[rspec-users] on
its own.)

I thought some more about the issue and I think I’m approaching the
the wrong way to begin with. As I understand it, part of the philosophy
RSpec is that using mocks and stubs when testing controllers and views
instead of touching the database helps to keep each test context
self-contained. So I really ought to be checking to see if
Membership.create or or is being called instead of
the model object’s relationships themselves - not that I can anyway,
it’s a mock model.

Can anyone confirm if that sounds right? If so, what method should I be
using? #should_receive? Thanks again in advance.

On 2008-10-13, at 17:14, O. Frabjous-Dey wrote:

I be using? #should_receive? Thanks again in advance.
Hi O. You’re correct about using mocks and stubs to prevent hitting
the database. More importantly though, they allow you to test discrete
pieces of code without depending on the state of its surrounding code.

To spec the ‘create’ action, just go through it one “step” at a time.

describe “create” do
before :each do
@group = mock_model Group, :save => true
# somehow spec the assignment to flash[:notice]
Membership.stub! :create

it “should create a new group”
it “should respond to …”
it “should save the group”
it “should assign the flash message”
it “should create a new Membership”

That doesn’t seem complete. What’d I miss? =P