我正在测试我的控制器,并且有一个产生AR查询的字符串: current_user.providers.find(params[:id])
。我需要它返回到我测试的对象,否则,控制器获取的参考信息与我在spec中的参考信息不同,并且某些存根(如allow(provider).to receive(:recreate)
)不起作用。receive_message_chain和臭味代码
我发现要做到这一点的唯一方法是使用这样的receive_message_chain
: allow(provider.user).to receive_message_chain(:providers, :find => provider)
。但是rspec文档says考虑使用receive_message_chain
作为有异味的代码。 另外,我想后面我可能需要用另一个ID调用current_user.providers.find(otherid)
来获得另一个对象,这样就不再适合我了。
有什么办法可以做得更好吗?我已经设法避免allow_any_instance_of
,这也被认为是臭,所以我相信有一种方法可以避免这一点,我只是看不到它。 如果没有,我至少想知道是否有什么方法可以将with
添加到receive_message_chain
?
===========
我只是想测试我控制器的方法update
。
# app/controllers/restream/facebooks_controller.rb
class Restream::FacebooksController < Restream::BaseController
def update
current_user.providers.find(params[:id])
if @fb.update_attributes(facebook_params)
if event_changed?
@fb.recreate
else
@fb.update
end
redirect_to restreams_path
else
render 'edit'
end
end
end
#spec/controllers/restream/facebooks_controller_spec.rb
require 'rails_helper'
describe Restream::FacebooksController do
let!(:facebook) { create(:restream_facebook) }
let!(:restream) { facebook.restream }
before do
login(restream.user)
end
describe '#update' do
let!(:params_hash) { {
:title => facebook.title,
:privacy => facebook.privacy,
:destination => facebook.destination,
:destination_id => facebook.destination_id,
:description => facebook.description
} }
let!(:request_hash) { {
:restream_facebook => params_hash,
:id => facebook.id
} }
before do
allow(facebook.user).
to receive_message_chain(:providers, :find => facebook)
allow(facebook).to receive(:update)
allow(facebook).to receive(:recreate)
end
context 'updates' do
it 'title' do
params_hash[:title] = SecureRandom.hex(2)
post :update, request_hash
expect(facebook.reload.title).to eq params_hash[:title]
end
end
end
end
我无法永久删除'current_user'。而且我不想拥有一个像'if Rails.env.test?'这样的字符串。或者你的意思是我可以用其他方式做到吗? – Ngoral
您在文章的第一句中引用的控制器方法,我会建议用'Provider.find(params [:id])替换它,因为它应该像'current_user'一样工作。如果它为你产生相同的行为,那么你的测试代码看起来好像更容易运行,因为方法链较少。这可能有助于编辑您的帖子更多的代码示例,因为我可以在我的假设中脱颖而出。 – abax
我可以轻松地添加更多的代码示例,只是不知道究竟是什么。 我试过使用'allow(Provider).to接收(:find).with(provider.id).and_return provider',但由于某种原因,这并不起作用。 – Ngoral