In Making a Mockery of ActiveRecord, a single test has multiple expectations set up for accessor methods…
specify "should create EmailMessages and Subscriptions when include_subscribers is true" do @message.include_subscribers = true @message.should_receive(:lists).and_return([@list]) @message.should_receive(:campaign).twice.and_return(@campaign) @list.should_receive(:people).and_return([@person]) @person.should_receive(:campaigns).and_return()
@person.should_receive(:subscriptions).and_return(@subscriptions) @subscriptions.should_receive(:create).and_return(nil) @campaign.should_receive(:people).and_return()
message.generate # I think this line is missing from the original test @message.should_have(1).email_messages end
A query in this context is a method which does not change the state of the object on which it is called. The accessor methods definitely fall into this category, so I would stub them, not set expectations for them. The one command method in the above example which merits an expectation is the call to
def test_should_create_email_messages_and_subscriptions_when_include_subscribers_is_true subscriptions = mock() person = Person.new(:campaigns => ) person.stubs(:subscriptions).returns(subscriptions) list = List.new(:people => [person]) campaign = Campaign.new(:people => ) message = Message.new(:lists => [list], :campaign => campaign) message.include_subscribers = true
message.generate assert_equal 1, message.email_messages end
I haven’t actually run this – so it’s quite likely there are errors in it, but you should get the general idea. The
person.stubs line is necessary to avoid the type checking that Luke Redpath mentions in his comment.
More thoughts here.