使用Sorcery和RSpec测试身份验证

时间:2014-01-01 21:03:36

标签: ruby-on-rails rspec sorcery

在寻求帮助之前,我花了太长时间搞乱这个。我似乎无法让RSpec和Sorcery很好地一起玩。我已经阅读了Integration testing with Sorcery上的文档并且可以正确发布登录操作,但我的测试仍然不认为用户已登录。

# spec/controllers/user_controller_spec
describe 'user access' do
    let (:user) { create(:user) }

    before :each do
      login_user(user[:email], user[:password])
    end

    it "should log in the user" do
      controller.should be_logged_in
    end

end

我的login_user方法

# spec/support/sorcery_login
module Sorcery
  module TestHelpers
    module Rails
      def login_user email, password
        page.driver.post(sessions_path, { email: email , password: password, remember_me: false })
      end
    end
  end
end

当我在生成的页面上使用它们时,会话控制器正确处理页面。我尝试输出login_user方法的结果,它似乎正确发布数据。如何通过测试保持此登录用户?有一个之前:每个块不适用于此?我只是不确定它在哪里运行错误而且我对测试/ RSpec很新,所以我可能会遗漏一些明显的东西。我很感激任何帮助。

以下是失败测试的输出:

1) UsersController user access should log in the user
    Failure/Error: controller.should be_logged_in
    expected logged_in? to return true, got false

4 个答案:

答案 0 :(得分:1)

您是否尝试添加到spec / spec_helpers。

RSpec.configure do |config|
  # ...
  config.include Sorcery::TestHelpers::Rails::Controller
end

请注意,您需要包含Sorcery::TestHelpers::Rails::Controller,而不仅仅是Sorcery::TestHelpers::Rails

然后您可以从任何控制器规范中login_user获得:

describe CategoriesController do

  before do
    @user = FactoryGirl::create(:user)
  end

  describe "GET 'index'" do
    it "returns http success" do
      login_user
      get 'index'
      expect(response).to be_success
    end
  end
end

答案 1 :(得分:0)

我昨天刚刚经历过这个。这就是我做的,如果有帮助的话。

Sorcery提供了一个依赖于login_user对象可用的测试助手@controller。这在控制器规范中很有用,但在集成测试中不起作用。因此,集成测试中的解决方法是编写另一种方法(如上所述),以模拟通过HTTP请求实际登录(基本上模拟提交表单)。

所以我首先想到的是你应该尝试将你的方法重命名为login_user_post或其他不会与内置测试助手发生冲突的东西。

另一个潜在的问题是,我认为Sorcery助手会假设您的用户密码是“秘密”。

这是内置助手的链接,以便您可以看到我在说什么:

https://github.com/NoamB/sorcery/blob/master/lib/sorcery/test_helpers/rails.rb

祝你好运 - 除了这部分,我真的很喜欢这个宝石。实际上只有通过修补SO帖子才能完全解释。这是我使用的代码:

整合助手

module Sorcery
  module TestHelpers
    module Rails
      def login_user_post(user, password)
        page.driver.post(sessions_url, { username: user, password: password}) 
      end

      def logout_user_get
        page.driver.get(logout_url)
      end
    end
  end
end

Integration Spec (用户需要登录才能执行操作)

  before(:each) do
    @user = create(:user)
    login_user_post(@user.username, 'secret')
  end

控制器规范(常规login_user帮助程序正常工作)

  before(:each) do
    @user = create(:user)
    login_user
  end

请注意,如果您的@user对象的密码为“secret”,则login_user不需要任何参数。

答案 2 :(得分:0)

传递密码的方式可能不对。此时可能会加密。在提供的示例中,我将首先尝试执行此操作:

describe 'user access' do
    let (:user) { create(:user, password: 'secret') }

    before :each do
      login_user(user[:email], 'secret')
    end

    it "should log in the user" do
      controller.should be_logged_in
    end
end

答案 3 :(得分:0)

这似乎记录很差。上述解决方案对我不起作用。以下是我如何使用它:

检查sessions_url。确保它是正确的。另外,请检查登录所需的参数。可能是emailusername等。

module Sorcery
  module TestHelpers
    module Rails
      def login_user_post(email, password)
        page.driver.post(sessions_url, { email:email, password: password }) 
      end
    end
  end
end

RSpec配置:

config.include Sorcery::TestHelpers::Rails

Spec helper:

def app
  Capybara.app
end

规格/控制器/ protected_resource_spec.rb:

describe UsersController do
  before do
    # Create user

    # Login
    response = login_user_post( user.email, :admin_password )
    expect( response.headers[ 'location' ]).to eq 'http://test.host/' 
    # I test for login success here. Failure redirects to /sign_in.

    @cookie = response.headers[ 'Set-Cookie' ]
  end

  specify 'Gets protected resource' do
    get protected_resource, {}, { cookie:@cookie }
    expect( last_response.status ).to eq 200
  end