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

rec*_*nym 8 rspec ruby-on-rails

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

MyClass.stub(:new).with('these' => 'params') { mock_my_class(:save => true) }
Run Code Online (Sandbox Code Playgroud)

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

测试失败

expected: ({"these"=>"params"})
got: ({"these"=>"params", "user_id"=>315})
Run Code Online (Sandbox Code Playgroud)

测试失败是有道理的,因为新方法接收到它没有预料到的参数.它预计会收到{'these'=>'params'}但它实际收到{'these'=>'params','user_id'=> 1234}

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

所以我添加测试如下:

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

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

expected: ({"these"=>"params", "user_id"=>298})
got: ({"these"=>"params"})
Run Code Online (Sandbox Code Playgroud)

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

有帮助吗?:)

注意:

rspec网站说如下:

Account.should_receive(:find).with("37").and_return(account)
Run Code Online (Sandbox Code Playgroud)

要么

Account.stub!(:find).and_return(account)
Run Code Online (Sandbox Code Playgroud)

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


通行证

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
Run Code Online (Sandbox Code Playgroud)

失败

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
Run Code Online (Sandbox Code Playgroud)

zet*_*tic 5

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

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

post :create, :forum_sub_topic => {:user_id=>@user.id}
Run Code Online (Sandbox Code Playgroud)

these_params密钥被生成作为一个例子-中移除,然后添加任何参数都需要控制器来创建MyClass

关于with选项:stubandshould_receive只会剔除满足指定条件的消息,即如果你这样做:

MyClass.stub(:new) {mock_model(MyClass,:save=>true)}
Run Code Online (Sandbox Code Playgroud)

然后 MyClass 将new使用模拟响应任何消息。另一方面,如果你这样做:

MyClass.stub(:new).with({:bogus=>37}) {mock_model(MyClass,:save=>true)}
Run Code Online (Sandbox Code Playgroud)

然后 MyClass 只会new在它也{:bogus=>37}作为参数接收时做出响应。