如何使用 rspec 测试这样的代码?
Foo.create! do |foo|
foo.description = "thing"
end
我不想测试对象是否已创建——我想测试是否使用正确的对象调用了正确的方法。相当于测试这个:
Foo.create!(description: "thing")
有了这个:
Foo.should_receive(:create!).with(description: "thing")
如何使用 rspec 测试这样的代码?
Foo.create! do |foo|
foo.description = "thing"
end
我不想测试对象是否已创建——我想测试是否使用正确的对象调用了正确的方法。相当于测试这个:
Foo.create!(description: "thing")
有了这个:
Foo.should_receive(:create!).with(description: "thing")
这就是你所追求的吗?
it "sets the description" do
f = double
Foo.should_receive(:create!).and_yield(f)
f.should_receive(:description=).with("thing")
Something.method_to_test
end
Foo.count.should == 1
Foo.first.description.should == 'thing'
这是一种组合方法,它融合了@antiqe 和@Fitzsimmons 的最佳答案。不过,它要冗长得多。
这个想法是以更像 AR::Base.create 的方式模拟 Foo.create。首先,我们定义一个辅助类:
class Creator
def initialize(stub)
@stub = stub
end
def create(attributes={}, &blk)
attributes.each do |attr, value|
@stub.public_send("#{attr}=", value)
end
blk.call @stub if blk
@stub
end
end
然后我们可以在我们的规范中使用它:
it "sets the description" do
f = stub_model(Foo)
stub_const("Foo", Creator.new(f))
Something.method_to_test
f.description.should == "thing"
end
您也可以使用FactoryGirl.build_stubbed
代替stub_model
. 但是,您不能使用mock_model
,mock
或者double
因为您会再次遇到相同的问题。
现在,您的规范将通过以下任何代码片段:
Foo.create(description: "thing")
Foo.create do |foo|
foo.descrption = "thing"
end
foo = Foo.create
foo.descrption = "thing"
反馈表示赞赏!