假设我的虚拟模型有一个虚拟演示器类,如下所示:
class DummyPresenter
def initialize(dummy_id)
@dummy = DummyModel.find(dummy_id)
end
def id
@dummy.id
end
def change_child_dummy_name(child_dummy_id, new_child_dummy_name)
child_dummy = @dummy.child_dummies.find(child_dummy_id)
child_dummy.update_attributes(:display_name => new_child_dummy_name)
child_dummy # I need to return a child_dummy object here!!
end
end
在我的规范中:
require 'spec_helper'
describe DummyPresenter do
before :all do
@dummy_presenter = DummyPresenter.new(1)
@child_dummy = DummyModel.find(1).child_dummies.first
end
it 'should update the display name of a child dummy for a dummy' do
expect(@child_dummy.display_name).to be_nil
@dummy_presenter.change_child_dummy_name(@child_dummy.id, 'Child Dummy network')
@child_dummy.reload
expect(@child_dummy.display_name).to eq('Child Dummy network')
end
it 'should return updated child dummy' do
child_dummy_id = @child_dummy.id
@dummy_presenter.should_receive(:change_child_dummy_name).at_least(:once).with(child_dummy_id, 'Child Dummy network').and_return(@child_dummy)
@dummy_presenter.change_child_dummy_name(child_dummy_id, 'Child Dummy network')
end
end
以上测试用例通过,没有任何问题。
现在,根据我的理解,第一个it
块在我只看到更新的属性的地方工作得很好。但是,我期望方法的第二个块:change_child_dummy_name
返回@child_dummy
不工作,或者可能我没有理解我在这里正确编写的代码。因为,当我改变change_child_dummy_name
方法在演示器为这个:
def change_child_dummy_name(child_dummy_id, new_child_dummy_name)
child_dummy = @dummy.child_dummies.find(child_dummy_id)
child_dummy.update_attributes(:display_name => new_child_dummy_name)
"child_dummy" # A String!! Where as I need to return a child_dummy object here!!
end
规格再次通过,没有引发任何错误。那么,我做错了什么?
如果我没弄错的话,这个问题的实质在这里
@dummy_presenter.should_receive(:change_child_dummy_name).at_least(:once).with(child_dummy_id, 'Child Dummy network').and_return(@child_dummy)
should_receive
实际上存根方法的结果。
如果使用and_returns
,则其操作数为新值,如果不使用存根值为nil
。
在您的例子中,它是@child_dummy
对象。顺便说一下,这也是你第一次考试通过的原因!
.and_call_original
,它将完成您所期望的。
您应该将其重写为两个测试:
- 一个测试
change_child_dummy_name
被调用(也许这是不必要的) - 将测试
@child_dummy
所需的属性(因为您在rspec测试中创建的对象与方法将返回的对象不同)。