这里发生了什么:rspec stub(:new).with ...?

时间:2011-05-16 03:36:10

标签: ruby-on-rails rspec

我对rspec生成的脚手架控制器规格发生了什么感到困惑。在我向我的应用程序添加授权之前,它似乎有意义,现在我需要更新我的测试。

MyClass.stub(:new).with('these' => 'params') { mock_my_class(:save => true) }

在我的控制器中,我在创建新记录时将哈希合并到params中(它需要current_user id有效)。 MyClass.new(params [:my_class] .merge(:user_id => current_user.id))

测试失败

expected: ({"these"=>"params"})
got: ({"these"=>"params", "user_id"=>315})

测试失败是有道理的,因为新方法接收了它没想到的参数。它预计会收到{'这些'=> 'params'}但它确实收到了''这些'=> 'params','user_id'=> 1234}

所以我的自然反应是调整测试,因为新方法应该接收{'这些'=> 'params','user_id'=> 1234}并返回模拟对象。

所以我按如下方式添加测试:

   MyClass.stub(:new).with({'these' => 'params', 'user_id' => @user.id}) { mock_my_class(:save => true) }   

这是我通过循环抛出的地方。测试结果如下:

expected: ({"these"=>"params", "user_id"=>298})
got: ({"these"=>"params"})

似乎一次成功的测试神奇地躲避了我。我确信这些结果有合理的原因,但我似乎无法弄明白。

有任何帮助吗? :)

请注意:

rspec网站说明如下:

Account.should_receive(:find).with("37").and_return(account)

Account.stub!(:find).and_return(account)

这很容易跟随它只是看起来很奇怪所生成的脚手架不会包含这些方法(除非我拙劣的东西是可能的(:)


通行证

login_admin
describe "with valid params" do
  it "assigns a newly created forum_sub_topic as @forum_sub_topic" do
    ForumSubTopic.stub(:new) { mock_forum_sub_topic(:save => true) }
    ForumSubTopic.should_receive(:new).with({"these"=>"params", "user_id"=> @admin.id})  #PASS!
    post :create, :forum_sub_topic => {'these' => 'params'}
    assigns(:forum_sub_topic).should be(mock_forum_sub_topic) #PASS!
  end
end

失败

login_admin
describe "with valid params" do
  it "assigns a newly created forum_sub_topic as @forum_sub_topic" do
    ForumSubTopic.stub(:new).with({'these' => 'params', 'user_id' => @user.id}) { mock_forum_sub_topic(:save => true) } 
    post :create, :forum_sub_topic => {'these' => 'params'}
    assigns(:forum_sub_topic).should be(mock_forum_sub_topic)
  end
end

1 个答案:

答案 0 :(得分:4)

正如俗话所说,“永远不要相信一个瘾君子”。也可以说,“永远不要相信脚手架”。

好的,那太苛刻了。脚手架尽力确定哪些参数适用于您正在生成的模型/控制器,但它不知道嵌套资源(我假设您正在使用它),因此它不会生成{{ 1:}在params哈希。补充一点:

user_id

生成post :create, :forum_sub_topic => {:user_id=>@user.id} 密钥作为示例 - 将其删除并添加控制器创建these_params所需的任何参数。

关于MyClass选项:withstub只会删除符合指定条件的邮件,例如:

should_receive

然后MyClass将使用模拟响应任何MyClass.stub(:new) {mock_model(MyClass,:save=>true)} 消息。另一方面,如果你这样做:

new

然后,当MyClass收到MyClass.stub(:new).with({:bogus=>37}) {mock_model(MyClass,:save=>true)} 作为参数时,它才会回复new