我有一些嵌套模型需要比标准accepts_nested_attributes_for
逻辑多一点。而不是基于id键自动创建或更新子记录,在这种情况下,子记录必须已经存在并具有某些其他条件,否则会引发错误。
作为其中的一部分,我有一个父模型迭代给定的子属性并在匹配的子记录上调用#update_attributes。
我的问题是如何在父模型的规范中模拟#update_attributes
。我想测试由给定属性标识的子记录实际上是接收#update_attributes
我的第一种方法是尝试mock_model,类似这样(不使用实际的模型名称,但为了清晰起见,只是'主题'和'儿童'):
before :each do
subject.children = mock_model(Child), mock_model(Child), mock_model(Child)
subject.save!
@expected = subject.children[1]
@input = {:child_id => @expected.id, :value => 'something'}
end
it 'should call #update_attributes on the child with given attributes' do
@expected.should_receive(:update_attributes).
with({:value => 'something'})
subject.merge_children_attributes(@input)
end
但是,你实际上不能坚持模拟模型。并且出于同样的原因,您不能使用存根模型。我需要持久化记录,因为我在实现中使用children.find()
或children.all()
。 (除非我嘲笑children
关联,这似乎不对,因为它是一个主题的方法)。
然后我去了固定装置。
fixtures :children
before :each do
subject.children = children(:one), children(:two), children(:three)
subject.save!
@expected = subject.children[1]
@input = {:child_id => @expected.id, :value => 'something'}
end
it 'should call #update_attributes on the child with given attributes' do
@expected.should_receive(:update_attributes).
with({:value => 'something'})
subject.merge_children_attributes(@input)
end
这里的问题是预期的匹配记录(@expected
)从未收到:update_attributes
- 任何内容。
大约puts
,原因是当实现调用children.find()
时,它会返回不同的实例而不是@expected = subject.children[1]
规范。虽然:id属性是相同的。 ActiveRecord没有身份地图......
那么如何编写此规范才能通过?
更新
我确认在日志中查看正确的记录实际上正在更新。所以令人沮丧的是,我似乎无法模仿:update_attributes
,因为find
之间没有维护对象身份。
答案 0 :(得分:0)
并不是一个令人满意的答案,但我通过规范的方法是删除Child.find
(当您对子关联进行查找时是底层调用) - 返回一个模拟子项的数组我可以设定期望。所以:
before :each do
@children = [ mock_model(Child), mock_model(Child), mock_model(Child) ]
Child.should_receive(:find).and_return(@children)
@expected= @children[1]
@input = {:child_id => @expected.id, :value => 'something'}
end
it 'should call #update_attributes on the child with given attributes' do
@expected.should_receive(:update_attributes).
with({:value => 'something'})
subject.merge_children_attributes(@input)
end
不是那么令人满意,因为在实现中只期望一个children.find(:all)
似乎过于假设放入规范。不太可能,但是谁说不可能有一个调用多个children.find()
的实现呢?