RSpec“未定义的方法”在Rails 4中的顺序依赖错误,在Rails 3.2中工作。

时间:2023-01-16 10:00:20

I have been using a testing workflow in Rails 3.2 for a few months that I picked up from a screencast by Rem Zolotykh. It is simple and useful for verifying the basic components of the Rails stack. However, I am using it in Rails 4.0.0 for the first time and I am getting an order dependency error where I have not had one before. This is the UsersController spec:

我已经在Rails 3.2中使用了一个测试工作流,几个月后我从Rem Zolotykh的一个屏幕上发现了它。它对于验证Rails堆栈的基本组件非常简单和有用。但是,我第一次在Rails 4.0.0中使用它,并且我得到了一个订单依赖错误,我以前没有这样做过。这是UsersController规范:

require 'spec_helper'

需要“spec_helper”

describe UsersController do 
  describe 'POST create' do
    let!(:user) { stub_model(User) }
    it 'sends new message to User class' do # this is the one that fails intermittently
      params = {                            # call this spec 1
        'first_name' => 'Test',
        'last_name' => 'Tester',
        'email_address' => 'test@test.com',
        'password' => 'secret',
        'password_confirmation' => 'secret'
      }
      User.stub(:new).and_return(user)
      User.should_receive(:new).with(params)
      post :create, user: params
    end
    it 'sends save message to user model' do # this one always passes
      User.stub(:new).and_return(user)       # call this spec 2
      user.should_receive(:save)
      post :create
    end
  end
end

This is the UsersController:

这是UsersController:

class UsersController < ApplicationController
  def new
    @user = User.new
  end

  def create
    user = User.new(params[:user])
    user.save
    render nothing: true
  end
end

Should be very simple. However, when the random test order fires Spec 2 first, then spec 1 passes. If spec 1 is fired first, it fails but spec 2 still passes. The failure error for spec 1:

应该很简单的。但是,当随机测试顺序先触发Spec 2,然后Spec 1通过。如果spec 1首先被触发,它会失败,但是spec 2仍然会通过。规范1的失败错误:

1) UsersController POST create sends new message to User class
 Failure/Error: post :create, user: params
 NoMethodError:
   undefined method `save' for #<User:0x007f9d1b6baf98>
 # ./app/controllers/users_controller.rb:8:in `create'
 # ./spec/controllers/users_controller_spec.rb:32:in `block (3 levels) in <top (required)>'

I am using rspec-core 2.13.1 and rspec-rails 2.13.2. I've searched high and low and I have found nothing. Any ideas?

我使用的是rspeccore 2.13.1和rspecrails 2.13.2。我到处寻找,却什么也没找到。什么好主意吗?

1 个解决方案

#1


0  

Yes, I think so.

是的,我是这样认为的。

In case 1, User.new has been stubbed to return the memoized stub_model. The stub model doesn't have a save method, though, so you get an error when you do the post :create, which in turns invokes new and then calls save on the result.

在案例1中,用户。new已经被存根化以返回memoized stub_model。但是,存根模型没有保存方法,所以当您执行post:create时,会出现一个错误:create,它会调用new,然后调用save。

If you execute the second spec 1st, it creates an expectation on the stub_model that save will be called, so case 1 passes.

如果您执行第二个spec 1,它会在stub_model上创建一个期望,保存将被调用,所以case 1通过。

What I'm confused by is that let should not be caching results across examples, as described in https://www.relishapp.com/rspec/rspec-core/v/2-6/docs/helper-methods/let-and-let, so I would think case 1 should still fail even if case 2 is executed first.

让我感到困惑的是,我们不应该在示例中缓存结果,如https://www.relishapp.com/rspec/rspec-core/v/2-6/docs/helper-methods/let,所以我认为即使case 2首先被执行,case 1仍然会失败。

As for why this would be different between 3.2 and 4.0, I have no idea. Good luck.

至于为什么会在3.2和4.0之间有所不同,我不知道。祝你好运。

#1


0  

Yes, I think so.

是的,我是这样认为的。

In case 1, User.new has been stubbed to return the memoized stub_model. The stub model doesn't have a save method, though, so you get an error when you do the post :create, which in turns invokes new and then calls save on the result.

在案例1中,用户。new已经被存根化以返回memoized stub_model。但是,存根模型没有保存方法,所以当您执行post:create时,会出现一个错误:create,它会调用new,然后调用save。

If you execute the second spec 1st, it creates an expectation on the stub_model that save will be called, so case 1 passes.

如果您执行第二个spec 1,它会在stub_model上创建一个期望,保存将被调用,所以case 1通过。

What I'm confused by is that let should not be caching results across examples, as described in https://www.relishapp.com/rspec/rspec-core/v/2-6/docs/helper-methods/let-and-let, so I would think case 1 should still fail even if case 2 is executed first.

让我感到困惑的是,我们不应该在示例中缓存结果,如https://www.relishapp.com/rspec/rspec-core/v/2-6/docs/helper-methods/let,所以我认为即使case 2首先被执行,case 1仍然会失败。

As for why this would be different between 3.2 and 4.0, I have no idea. Good luck.

至于为什么会在3.2和4.0之间有所不同,我不知道。祝你好运。