简体   繁体   English

Rails集成测试与设计宝石

[英]Rails integration test with the devise gem

I want to write an rails integration test (with ActionDispatch::IntegrationTest ). 我想写一个rails集成测试(使用ActionDispatch::IntegrationTest )。 I am using devise for authentication and machinist for test models. 我正在使用设计验证和测试模型的机械师。 I cannot successfully sign in. 我无法成功登录。

Here is a simple example: 这是一个简单的例子:

class UserFlowsTest < ActionDispatch::IntegrationTest
  setup do
    User.make
  end
  test "sign in to the site" 
    # sign in
    post_via_redirect 'users/sign_in', :email => 'foo@bar.com', :password => 'qwerty'    
    p flash
    p User.all
end

Here is the debug output: 这是调试输出:

Loaded suite test/integration/user_flows_test
Started
{:alert=>"Invalid email or password."}
[#<User id: 980190962, email: "", encrypted_password: "", password_salt: "", reset_password_token: nil, remember_token: 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, created_at: "2010-11-27 16:44:10", updated_at: "2010-11-27 16:44:10">, #<User id: 980190963, email: "foo@bar.com", encrypted_password: "$2a$10$vYSpjIfAd.Irl6eFvhJL0uAwp4qniv5gVl4O.Hnw/BUR...", password_salt: "$2a$10$vYSpjIfAd.Irl6eFvhJL0u", reset_password_token: nil, remember_token: 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, created_at: "2010-11-27 17:09:13", updated_at: "2010-11-27 17:09:13">]
"/unauthenticated"
F

Here is my blueprints.rb: 这是我的blueprints.rb:

require 'machinist/active_record'
require 'sham'

User.blueprint do
  email {"foo@bar.com"}
  password {"qwerty"}
end

The reason it doesn't work is devise creates form field names as 它不起作用的原因是设计创建表单字段名称为

'user[email]'
'user[password]'

and post_via_redirect expects those names as arguments. 和post_via_redirect期望这些名称作为参数。 So following statement would make a successful login. 因此,以下声明将成功登录。

post_via_redirect 'users/sign_in', 'user[email]' => 'foo@bar.com', 'user[password]' => 'qwerty' 

First of all, with devise, you may have to "confirm" the user. 首先,通过设计,您可能必须“确认”用户。

you can do something like this: 你可以这样做:

user = User.make!
user.confirmed_at = Time.now
user.save!

Here is an example without Machinist (but you just have to replace the user creation code portion with the part above): 这是一个没有Machinist的例子(但你必须用上面的部分替换用户创建代码部分):

into test_integration_helper: 进入test_integration_helper:

require "test_helper"
require "capybara/rails"

    module ActionController
      class IntegrationTest
        include Capybara

        def sign_in_as(user, password)
           user = User.create(:password => password, :password_confirmation => password, :email => user)
           user.confirmed_at = Time.now 
           user.save!
           visit '/'
           click_link_or_button('Log in')
           fill_in 'Email', :with => user.email
           fill_in 'Password', :with => password
           click_link_or_button('Sign in')
           user      
         end 
         def sign_out
            click_link_or_button('Log Out')   
         end
      end
    end

And into your integration_test: 进入你的integration_test:

require 'test_integration_helper'

class UsersIntegrationTest < ActionController::IntegrationTest

  test "sign in and then sign out" do 
    #this helper method is into the test_integration_helper file                   
    sign_in_as("lolz@gmail.com", "monkey")         
    assert page.has_content?('Signed in successfully'), "Signed in successfully"

    sign_out         
    assert page.has_content?('Signed out successfully'), "Signed out successfully" 
  end
end

I don't have a sample integration test in the book for Devise, but I think the code in the step definition in the Cucumber chapter will also work if you have Webrat/Capybara installed: 我没有在Devise的书中进行样本集成测试,但我认为如果安装了Webrat / Capybara,Cucumber章节中步骤定义中的代码也会起作用:

@user = User.create!(:email => "email@email.com",  
            :password => "password",  
            :password_confirmation => "password")
visit "login"  
fill_in("user_email", :with => @user.email)  
fill_in("user_password", :with => "password") 
click_button("Sign In")

In case anyone else has a similar problem... 如果其他人有类似的问题......

I was in a similar situation (migrating from Authlogic), and had this exact same problem. 我处于类似的情况(从Authlogic迁移),并有这个完全相同的问题。 The issue was in the devise.rb initializer. 问题出在devise.rb初始化程序中。 By default it sets up your test environment to use only 1 stretch during the encryption/decryption of passwords. 默认情况下,它会将您的测试环境设置为在加密/解密密码期间仅使用1次拉伸。 I honestly don't know what a stretch is, but for Devise to work with old Authlogic encrypted passwords, the stretches has to be 20. Since I was trying to sign in a user that originally had their password encrypted by Authlogic in my test, Devise needs to use 20 stretches in test also. 老实说,我不知道是什么延伸,但是对于Devise使用旧的Authlogic加密密码,延伸必须是20.因为我试图在我的测试中签署一个最初由Authlogic加密密码的用户,设计也需要在测试中使用20个延伸。 I changed the config like below: 我更改了如下配置:

# Limiting the stretches to just one in testing will increase the performance of
# your test suite dramatically. However, it is STRONGLY RECOMMENDED to not use
# a value less than 10 in other environments.
-  config.stretches = Rails.env.test? ? 1 : 20
+  config.stretches = 20

Since you are using ActionDispatch::IntegrationTest , you can include the Devise::Test::IntegrationHelpers module and use the sign_in method instead (which you can pass a user to): 由于您使用的是ActionDispatch::IntegrationTest ,因此您可以包含Devise::Test::IntegrationHelpers模块并使用sign_in方法(您可以将用户传递给它):

class UserFlowsTest < ActionDispatch::IntegrationTest
  include Devise::Test::IntegrationHelpers

  test "sign in to the site" do
    sign_in users(:one)
  end
end

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM