开发者

testing a has_one relationship?

I have an object

class User < ActiveRecord::Base
  has_one :subscription
end

and I have this test:

  it "should increment shipped count when item_shipped" do
    @user.attributes = @valid_attributes
    @user.save

    subscription = mock_model(Subscription)
    subscription.stub!(:item_shipped!)
    subscription.stub!(:user_id)
    @user.subscription = subscription

    lambda{@user.item_shipped!}.should change{@user.shipped_count}.by(1)
  end

But I am getting an error:

1)
Spec::Mocks::MockExpectationError in 'User should increment shipped count when item_shipped'
Mock "Subscription_1113" received unexpected message :[]= with ("user_id", 922717357)
开发者_StackOverflow中文版./spec/models/user_spec.rb:29:

I am not sure how to mock this out and I can't seem to find any references to this kind of thing.


Instead of mocking Subscription, try stubbing out the methods on an actual Subscription instead:

subscription = Subscription.new
subscription.stub!(:item_shipped!)
subscription.stub!(:user_id)
@user.subscription = subscription

Mocks can be brittle. Any call to a mock must be anticipated and declared as an expectation. It doesn't appear that this particular test needs that model mocked in any case.

EDIT: Also remember to declare any return values that the calling class depends on. In your case this might look like:

subscription.stub!(:item_shipped!).and_return(true)
subscription.stub!(:user_id).and_return(@user.id)

etc.

Again, if you're not asserting that a method on your mocked model should be called, then the only thing mocking does here is make your test brittle. Mocks are meant for things like:

subscription.should_receive(:some_method).once

Otherwise you simply need to stub out methods that have undesirable side effects that don't concern your spec.


Setting up associations for tests is made easier with factories: (untested)

Factory.define :subscriber, :class => User do |f|
  f.name "Moe Howard"
  f.association :subscription, :factory => :subscription
end

Factory.define :subscription, :class => Subscription do |f|
end

it "should increment shipped count when item_shipped" do
  @user = Factory.create(:subscriber)
  lambda{@user.item_shipped!}.should change{@user.shipped_count}.by(1)
end

Of course you're not really testing the association here -- you're testing the item_shipped method, which is what you really wanted.


change: mock_model(Subscription) to mock_model(Subscription).as_null_object

which will allow for any messages to be sent to the object (assuming this is an acceptable behavior in your case)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜