好的,所以我一直在寻找修复这个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,因为我在测试中的其他地方使用它并且它有效。
我没有从这段代码中得到任何错误,它似乎没有正确地改变返回值。
答案 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
上截断方法链。