2016-11-20 158 views
0

我想添加一些自定义字段到用户注册,所以我覆盖了设计注册控制器。现在我正在尝试编写一个应该(我认为)创建一个新的未注册用户的测试。虽然测试失败,但我不确定要从这里进行故障排除。如何在重写设计控制器时测试注册?

# note: this is a dump of `:valid_attributes` by my test 
{"id"=>nil, "name"=>"Hans Swift", "email"=>"[email protected]", "encrypted_password"=>"$2a$04$T6mRo3Dzcv6iV7Kdh52E6OA0tAX7nE4y3skV2jzkD9CLr5v8Dri1K", "reset_password_token"=>nil, "reset_password_sent_at"=>nil, "remember_created_at"=>nil, "sign_in_count"=>0, "current_sign_in_at"=>nil, "last_sign_in_at"=>nil, "current_sign_in_ip"=>nil, "last_sign_in_ip"=>nil, "confirmation_token"=>nil, "confirmed_at"=>nil, "confirmation_sent_at"=>nil, "unconfirmed_email"=>nil, "failed_attempts"=>0, "unlock_token"=>nil, "locked_at"=>nil, "created_at"=>nil, "updated_at"=>nil} 
F 
Failures: 

    1) Users::RegistrationsController POST #create with valid params creates a new User 
    Failure/Error: 
     expect { 
     puts valid_attributes 
     post :create, {:user => valid_attributes}, valid_session 
     }.to change(User, :count).by(1) 

     expected #count to have changed by 1, but was changed by 0 
    # ./spec/controllers/users/registrations_controller_spec.rb:19:in `block (4 levels) in <top (required)>' 

有谁能提出一个理由,这个测试是无法创建用户?当我使用users/sign_up表单时,该应用程序正常工作,并且电子邮件到达我的收件箱。

./spec/controllers/users/registrations_controller_spec.rb

require 'rails_helper' 
require 'factory_girl_rails' 

RSpec.describe Users::RegistrationsController, type: :controller do 

    describe "POST #create" do 
    let(:valid_attributes) { FactoryGirl.build(:user_for_registration).attributes } 
    let(:invalid_attributes) { User.get_invalid_user.attributes } 
    let(:valid_session) { {} } 

    # Help Devise map routes from the test back to the original controller. 
    # See http://stackoverflow.com/questions/6659555/how-to-write-controller-tests-when-you-override-devise-registration-controller 
    before :each do 
     request.env['devise.mapping'] = Devise.mappings[:user] 
    end 

    context "with valid params" do 
     it "creates a new User" do 
     expect { 
      puts valid_attributes 
      post :create, {:user => valid_attributes}, valid_session 
     }.to change(User, :count).by(1) 
     end  
    end 

    end 

end 

./app/controllers/users/registrations_controller.rb

class Users::RegistrationsController < Devise::RegistrationsController 
    before_filter :configure_permitted_parameters, if: :devise_controller? 

    protected 

    # we have to explicitly permit params in overridden controllers like this 
    # see https://github.com/plataformatec/devise#strong-parameters 
    def configure_permitted_parameters 
    devise_parameter_sanitizer.permit(:sign_up) do |u| 
     u.permit(:name, :email, :password, :password_confirmation) 
    end 
    devise_parameter_sanitizer.permit(:account_update) do |u| 
     u.permit(:name, :email, :password, :password_confirmation, :current_password) 
    end 
    end 
end 

./spec/factories/users.rb

require 'ffaker' 

FactoryGirl.define do 
    factory :user do |u| 
    @pass = "password" 

    name FFaker::Name.name 
    email { |me| "#{name.to_s.gsub(/\s/,'.')}_#{rand(1000).to_s}@testing.com" } 
    password @pass 

    factory :user_for_registration do 
     password_confirmation @pass 
    end 

    factory :user_for_account_update do 
     password_confirmation @pass 
     current_password @pass 
    end 
    end 
end 
+1

我认为你通过请求传递了错误的参数。看起来你应该传递':name,:email,:password,:password_confirmation'而不是'encrypted_pa​​ssword'等。我没有发布它作为答案,因为我不是100%。检查日志并查看正在发送的参数。 – DickieBoy

+0

是的,那看起来没错。看起来我应该使用'FactoryGirl :: attributes_for(:user)'而不是'FactoryGirl :: build(:user).attributes'。当我改变测试通过。不知道当我开始使用FactoryGirl :: build()..嗯,很高兴知道,谢谢! – doub1ejack

+0

由此判断,'attributes_for'看起来像会在某些过滤器链运行后为您提供属性。您应该仔细研究一下,并将其作为答案发布。 – DickieBoy

回答

1

你说你的测试发布所有这些属性:

{ 
    "id"=>nil, 
    "name"=>"Hans Swift", 
    "email"=>"[email protected]", 
    "encrypted_password"=>"$2a$04$T6mRo3Dzcv6iV7Kdh52E6OA0tAX7nE4y3skV2jzkD9CLr5v8Dri1K", 
    "reset_password_token"=>nil, 
    "reset_password_sent_at"=>nil, 
    "remember_created_at"=>nil, 
    "sign_in_count"=>0, "current_sign_in_at"=>nil, 
    "last_sign_in_at"=>nil, 
    "current_sign_in_ip"=>nil, 
    "last_sign_in_ip"=>nil, 
    "confirmation_token"=>nil, 
    "confirmed_at"=>nil, 
    "confirmation_sent_at"=>nil, 
    "unconfirmed_email"=>nil, 
    "failed_attempts"=>0, 
    "unlock_token"=>nil, 
    "locked_at"=>nil, 
    "created_at"=>nil, 
    "updated_at"=>nil 
} 

首先,它实际上是POST操作下user钥匙所有这些,使控制器的PARAMS实际上user[id]user[name]等设计需要它的参数处于顶级水平,如下所示:

post :create, valid_attributes, valid_session 

二,属性肯定不是您的视图POST,而您的控制器仅允许name,emailpasswordpassword_confirmation。所以我认为在解决第一个问题后,您的测试请求仍然会被拒绝。要解决这些问题,请确保您的测试只发布这四个属性。

下一次,你可以通过运行只是单一的测试(rspec spec/controllers/users/registrations_controller_spec:123其中123是测试的行号),以及看你log/test.log获取有关测试失败的很好的提示。

一旦你通过了,我还会写一些测试来验证那些参数是必需的。

另外我看到你通过valid_session,我也会删除它。如果您已经登录,Devise不会让您注册。即使它是空的,包含它仍然看起来很混乱。

+0

真棒,我不知道'log/test.log' - 这是一个巨大的帮助。 – doub1ejack

+0

另外,对于你的第二点问题是我正在传递'FactoryGirl :: build(:user).attributes'而不是'FactoryGirl :: attributes_for(:user)',这就是为什么我有那么长的列表(数据库字段,实际上)而不是我需要的4个字段。 – doub1ejack