1

好的,所以我一直在寻找几天来修复这个错误,但我似乎无法找到答案。我正在尝试使用 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,因为我在测试的其他地方使用它并且它有效。

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

4

2 回答 2

1

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

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

由于您正在测试 ActiveModel::Dirty's 的结果#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

但是,您可以只存根changed?而不是查看值本身:

于 2013-07-10T19:57:00.513 回答
0

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

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

于 2013-07-10T19:56:34.430 回答