我编写了以下规范:
it "should call user.invite_friend" do user = mock_model(User, :id => 1) other_user = mock_model(User, :id => 2) User.stub!(:find).with(user.id).and_return(user) User.stub!(:find).with(other_user.id).and_return(other_user) user.should_receive(:invite_friend).with(other_user) post :invite, { :id => other_user.id }, {:user_id => user.id} end
但是当我运行规范
时,我收到以下错误NoMethodError in 'UsersController POST invite should call user.invite_friend' undefined method `find' for # Class:0x86d6918 app/controllers/users_controller.rb:144:in `invite' ./spec/controllers/users_controller_spec.rb:13:
错误是什么?没有.with它工作得很好,但我想要对stub方法的不同参数有不同的返回值。以下控制器的操作可能是相关的:
def invite me.invite_friend(User.find params[:id]) respond_to do |format| format.html { redirect_to user_path(params[:id]) } end end def me User.find(session[:user_id]) end
答案 0 :(得分:1)
出现错误是因为第一次调用find
时存根被“用完”了。第二个find
没有存根,因此您得到NoMethodError。
如果我错了,有人可以纠正我,但当你多次调用时,.with
似乎对存根有一个奇怪的影响。 Rspec似乎将相同参数类型的每个消息与单个存根相关联。但另一种参数类型有效地创建了不同的存根。因此,在您的情况下,您可以通过使用字符串调用第二个find
来修复它:
User.stub!(:find).with(other_user.id.to_s).and_return(other_user)
这对您来说很幸运,因为实际上控制器期望params
哈希中的字符串。
这不能回答更大的问题:如何使用相同参数类型的参数存根多个方法调用?根据我的经验,你不能这样做。
当然,你可以通过不指定参数来绕过它。在您的情况下,我会说测试find
本身与您的控制器无关 - 实际上,您正在测试ActiveRecord是否可以对主键进行数据库查找,主键已经过充分测试。因此,如果您只需要按正确的顺序将响应存根到find
,那么您可以这样做:
User.stub!(:find).and_return(user,other_user)