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之间有所不同,我不知道。祝你好运。