测试rspec中方法的返回值



假设我的虚拟模型有一个虚拟演示器类,如下所示:

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测试中创建的对象与方法将返回的对象不同)。

相关内容

  • 没有找到相关文章

最新更新