当我试图让 Devise 在我的控制器测试中正确登录时,我有一些有趣的行为。它似乎在某些情况下有效,但在其他情况下无效。我不确定这是 Devise 和 FactoryGirl 之间的交互还是其他工作。
首先,这是我的工厂:
factory :advisor do
  name "Jason Jones"
  association :user
  initialize_with {Advisor.find_or_create_by_name('Jason Jones')}
end
factory :client do
  name "Rich Homeowner"
  association :advisor
end
factory :user do
    email "jason@jones.com"
    password "testpassword"
    initialize_with {User.find_or_create_by_email('jason@jones.com')}
end
我的控制器:
class ClientsController < ApplicationController
  before_filter :authenticate_user!
 def destroy
    @client = current_user.advisor.clients.where(:id => params[:id]).first
    @client.destroy
    flash[:notice] = 'Client deleted.'
    redirect_to clients_path
  end
和我的控制器测试:
 describe "DELETE destroy" do
    it "should delete a client" do
        a = FactoryGirl.create(:advisor)
        c = FactoryGirl.create(:client, :advisor => a)
        login_user(a.user)
        expect{
          delete :destroy, :id => c.id
          response.should be_redirect
          assigns(:client).should eq(c)
        }.to change(Client, :count).by(-1)
      end
  end
login_user 规范助手是它变得时髦的地方。如果我取消注释下面的行,强制将用户设置为 FactoryGirl 对象,则测试通过。如果我留下评论,Devise 会尝试以传递的用户身份登录(我已通过调试验证是数据库中的同一用户),但它实际上并没有登录。在这两种情况下,sign_in 调用实际上返回相同的数组,但基于执行路径,控制器代码永远不会执行,因为 Devise 重定向到登录页面。
def login_user(user=nil)
   @request.env["devise.mapping"] = Devise.mappings[:user]
   if user.nil?
     user = FactoryGirl.create(:user)
   end
   # user = FactoryGirl.create(:user) # uncommenting this line causes test to pass
   sign_in user
 end
如何让 sign_in 正常工作?
作为记录,当涉及到 Rails 的 TDD 时,我花了 10 分钟让我的实际代码正常工作,并花 2 小时跳过障碍来让我的测试代码完成它应该做的事情。