当我试图让 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 小时跳过障碍来让我的测试代码完成它应该做的事情。