Rspec不允许我为“any?”设置返回值。存根或should_receive的方法

时间:2013-07-10 19:42:25

标签: ruby-on-rails ruby rspec

好的,所以我一直在寻找修复这个bug的日子,我似乎无法找到答案。我正在尝试用rspec测试我的rails应用程序,特别是现在正在进行控制器测试。

在我的控制器中我有方法

def update

  changes = @match_preference.changes

  ...

  if changes.values.collect(&:first).any?(&:nil?)
    flash[:notice] = 'Hello'
  end

  ...

end

在我的测试文件中我有这个

before :each do 
  @match_preference = FactoryGirl.create :match_preference
end

it "should do something on first change" do
  # Line I have been changing a lot
  @match_preference.changes.values.collect.stubs(:any?).returns(true)
  post :update
  flash.should_not be_nil
end

我也尝试用stub_chain和许多其他可能的答案替换该行。我发现问题与功能有关吗?当我删除该函数时,我可以更改collect的返回值,它始终有效。为什么不呢?允许我设置一个返回值?

我知道问题不在于@match_preferences,因为我在测试中的其他地方使用它并且它有效。

我没有从这段代码中得到任何错误,它似乎没有正确地改变返回值。

2 个答案:

答案 0 :(得分:1)

values.collect将返回一个新的哈希值,然后你将其存根。这与控制器处理的哈希值不同。

此外,您的@match_preference变量与控制器中的变量不同 - 您的控制器将执行查找和分配,因此您需要存根查找,或使用{{1} }。

因为你正在测试ActiveModel :: Dirty的MatchPreference.any_instance的结果,它返回一个哈希,只是stub #changes来返回一个填充的哈希:

changes

或者你可以找到你的发现者:

let(:match_preference) { FactoryGirl.create :match_preference }

it "should do something on first change" do
  MatchPreference.any_instance.stub(:changes).and_return({:bogus => [nil, "new"]})

  post :update
  flash.should_not be_nil
end

但是,你可以直接let(:match_preference) { FactoryGirl.create :match_preference } it "should do something on first change" do match_preference.some_attribute = "new value" MatchPreference.stub(:find).and_return(match_preference) post :update flash.should_not be_nil end 而不是查看值本身:

答案 1 :(得分:0)

问题是,每次调用collect方法时,都会创建一个新对象,因此对collect的一个结果进行存根操作不会对下一次调用返回的对象做任何操作。方法。您应该使用stub_chain代替(在ActiveRecord对象上存根方法链)。

请注意,您应该使用控制器检索的相同ActiveRecord对象,这可以确保这是对您的控制器操作进行的相应查询调用的存根。另一种可能性是在ActiveRecord类的any_instance上截断方法链。