我有一个对象
class User < ActiveRecord::Base
has_one :subscription
end
我有这个测试:
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
但是我收到了一个错误:
1)
Spec::Mocks::MockExpectationError in 'User should increment shipped count when item_shipped'
Mock "Subscription_1113" received unexpected message :[]= with ("user_id", 922717357)
./spec/models/user_spec.rb:29:
我不知道如何嘲笑这个,我似乎找不到任何关于此类事物的引用。
答案 0 :(得分:2)
不要嘲笑Subscription,而是尝试在实际的Subscription上删除方法:
subscription = Subscription.new
subscription.stub!(:item_shipped!)
subscription.stub!(:user_id)
@user.subscription = subscription
模拟可能很脆弱。必须预期对模拟的任何调用并将其声明为期望。似乎这个特定测试似乎不需要在任何情况下模拟该模型。
编辑:还记得声明调用类所依赖的任何返回值。在您的情况下,这可能看起来像:
subscription.stub!(:item_shipped!).and_return(true)
subscription.stub!(:user_id).and_return(@user.id)
等
同样,如果你没有断言你的模拟模型上的方法应该被调用,那么这里唯一的模拟就是让你的测试变得脆弱。模拟适用于以下内容:
subscription.should_receive(:some_method).once
否则,您只需要找出与您的规范无关的具有不良副作用的方法。
答案 1 :(得分:0)
使用factories :(未经测试)
可以更轻松地设置测试关联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
当然,你并没有真正测试这里的关联 - 你正在测试item_shipped
方法,这正是你真正想要的。
答案 2 :(得分:0)
将mock_model(Subscription)
更改为mock_model(Subscription).as_null_object
允许将任何消息发送到对象(假设这是您可接受的行为)