0

我正在使用 factory_girl_rails (4.2.1) 和 rspec-rails (2.14.0) 在 Rails 4 上测试一个简单的控制器。在测试错误案例时,我使用FactoryGirl.build构建无效User对象。但是,生成的对象在 ; 中不包含任何错误@user.errors。但expect(assigns(:user)).to have(1).errors_on(:email)在测试用例中仍然通过。为什么FactoryGirl生成的对象没有任何错误,rspec如何看到错误?

这是详细信息和代码。

控制器只需创建一个 User 对象,然后如果创建成功则重定向到验证页面,或者如果有任何错误则再次呈现表单。

class RegistrationController < ApplicationController
  def new
  end

  def create
    @user = User.create(params.required(:user).permit(:email, :password, :password_confirmation))

    if @user.errors.empty?
      redirect_to verify_registration_path
    else
      render :new
    end
  end  
end

在我的错误案例测试中,我User使用 FactoryGirl 创建了一个没有“电子邮件”的邮件。预计会@user.errors在“电子邮件”字段中创建一个错误条目并呈现 :new 模板。

describe RegistrationController do 

  #... Some other examples ...

  describe 'GET create' do
    def post_create(user_params)
      allow(User).to receive(:create).with(ActionController::Parameters.new({user: user_params})[:user]).and_return(FactoryGirl.build(:user, user_params))
      post :create, user: user_params
    end

    context 'without email' do
      before { post_create email: '', password: 'testing', password_confirmation: 'testing' }
      subject { assigns(:user) }

      it 'build the User with error' do
        expect(subject).to have(1).errors_on(:email)
      end

      it 'renders the registration form' do
        expect(response).to render_template('new')
      end
    end
  end
end

但是,当我运行测试用例时,只有'renders the registration form'示例失败,而另一个失败。

Failures:

  1) RegistrationController GET create without email renders the registration form
     Failure/Error: expect(response).to render_template('new')
       expecting <"new"> but rendering with <[]>
     # ./spec/controllers/registration_controller_spec.rb:51:in `block (4 levels) in <top (required)>'

Finished in 0.25726 seconds
6 examples, 1 failure

Failed examples:

rspec ./spec/controllers/registration_controller_spec.rb:50 # RegistrationController GET create without email renders the registration form

这里奇怪的是 rspec 似乎能够看到错误@user(因此第一个测试用例通过),但由于某些未知原因@user.error.empty?返回true控制器导致它重定向而不是呈现:new模板(因此第二个测试用例失败)。我还在调试器中确认@user.error确实是空的。

FactoryGirl 处理错误的方式有问题,还是我使用错误?

谢谢

4

1 回答 1

0

我想在这里提到两件事:
1. 可能你想使用“Post create”而不是“Get create”。
2. email 是否丢失是模型的问题,而不是控制器的问题。
如果电子邮件丢失,我建议您使用存根返回 false。

最简单的方法是:

User.any_instance.stub(:create).and_return(false)

也许您想更改控制器中的其他一些内容,例如“如果@user.errors.empty?”

编辑:对不起,“创建”实际上不会返回错误。

所以在你的控制器中

@user = User.new(.....)

if @user.save
  ...
else
  render :new

并在您的测试中使用

User.any_instance.stub(:save).and_return(false)
于 2013-09-29T21:51:00.183 回答