我正在使用Ruby 2.1.2和Rails 4.1.5完成树屋教程,我在auth教程中遇到了我的测试问题。
教程说这段代码应该通过:
def create
user = User.find(params[:email])
if user && user.authenticate(params[:password])
session[:user_id] = user.id
redirect_to todo_lists_path
else
flash.now[:error] = "There was an error logging in. Please check your email and password"
render action: 'new'
end
end
以下是我的测试:
describe "POST 'create'" do
context "with correct credentials" do
let!(:user){
User.create(
first_name: "Jason",
last_name: "Seifer",
email: "jason@teamtreehouse.com",
password: "teamtreehouse1234",
password_confirmation:"teamtreehouse1234")}
it "redirects to the todo list path" do
post :create, email: "jason@teamtreehouse.com", password: "treehouse1234"
expect(response).to be_redirect
expect(response).to redirect_to(todo_lists_path)
end
it "finds the user" do
expect(User).to receive(:find_by).with({email: "jason@teamtreehouse.com"}).and_return(user)
post :create, email: "jason@teamtreehouse.com", password: "treehouse1234"
end
it "authenticates the user" do
User.stub(:find_by).and_return(user)
expect(user).to receive(:authenticate)
post :create, email: "jason@teamtreehouse.com", password: "treehouse1234"
end
it "sets the user id in the session" do
post :create, email: "jason@teamtreehouse.com", password: "treehouse1234"
expect(session[:user_id]).to eq(user.id)
end
it "sets the flash success messagge" do
post :create, email: "jason@teamtreehouse.com", password: "treehouse1234"
expect(flash[:success]).to eq("Thanks for logging in!")
end
end
context "with blank credentials" do
it "renders the new template" do
post :create
expect(response).to render_template('new')
end
it "sets the flash error messagge" do
post :create, email: "jason@teamtreehouse.com", password: "treehouse1234"
expect(flash[:error]).to eq("There was an error logging in. Please check your email and password")
end
end
context "with incorrect credentials" do
let!(:user){
User.create(
first_name: "Jason",
last_name: "Seifer",
email: "jason@teamtreehouse.com",
password: "teamtreehouse1234",
password_confirmation:"teamtreehouse1234")}
it "renders the new template" do
post :create, email: user.email, password: "fuckingpassword"
expect(response).to render_template('new')
end
it "sets the flash error messagge" do
post :create, email: user.email, password: "fuckingpassword"
expect(flash[:error]).to eq("There was an error logging in. Please check your email and password")
end
end
end
这给了我错误undefined method `authenticate' for nil:NilClass
我通过测试的唯一方法是:
class UserSessionsController < ApplicationController
def new
end
def create
user = User.find_by(email: params[:email])
if user.nil?
flash[:error] = "There was an error logging in. Please check your email and password"
render action: 'new'
else
user.authenticate(params[:password])
session[:user_id] = user.id
flash[:success] = "Thanks for logging in!"
redirect_to todo_lists_path
end
end
end
我知道它很丑陋但它确实有效,我需要测试它是否拒绝使用正确的用户进行身份验证但密码错误。测试返回了两个错误:
1) UserSessionsController POST 'create' with incorrect credentials renders the new template
Failure/Error: expect(response).to render_template('new')
expecting <"new"> but rendering with <[]>
2) UserSessionsController POST 'create' with incorrect credentials sets the flash error messagge
Failure/Error: expect(flash[:error]).to eq("There was an error logging in. Please check your email and password")
expected: "There was an error logging in. Please check your email and password"
got: nil
第一个例子失败了,因为无论什么原因(可能是rspec)if子句都不处理user.authenticate(params [:password])因为它返回一个哈希值。
请注意,以下代码适用于bin / rails控制台:
> user = User.create(first_name:"John", last_name: "Doe", email: "jon.doe@me.com", password: "password", password_confirmation: "password")
> user.save
> if user && user.authenticate("password")
> puts "wawa"
> end
wawa
=> nil
我尝试过重构create方法,以便在分配时进行身份验证无效:
def create
user = User.find_by(email: params[:email]).authenticate(params[:password])
if user.nil? || user == false
flash[:error] = "There was an error logging in. Please check your email and password"
render action: 'new'
else
session[:user_id] = user.id
flash[:success] = "Thanks for logging in!"
redirect_to todo_lists_path
end
end
我再次获得undefined method `authenticate' for nil:NilClass
。
答案 0 :(得分:1)
发现它不在测试中的逻辑中的错误,我使用不正确的凭据treehouse123
测试密码,而不是在我的用户teamtreehouse123
中创建的密码。
灵感来自于这个调试代码:
def create
user = User.find_by(email: params[:email])
if (user.nil? == false)
if user.authenticate(params[:password])
puts user.authenticate(params[:password])
puts "NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN Batman!"
session[:user_id] = user.id
flash[:success] = "Thanks for logging in!"
redirect_to todo_lists_path
else
puts user.authenticate(params[:password])
puts "waka waka waka waka waka waka waka waka waka waka waka waka waka waka waka waka"
flash[:error] = "There was an error logging in. Please check your email and password"
render action: "new"
end
else
flash[:error] = "There was an error logging in. Please check your email and password"
render action: "new"
end
end
user.authenticate(params[:password])
总是返回false,无论我做了什么。
树屋代码是正确的,但我将所有teamtreehouse123
更改为password
。
答案 1 :(得分:0)
undefined method 'authenticate' for nil:NilClass
是一个经典的Rails错误。
authenticate
方法中的错误从不。它总是在它之前的部分。
此处,User.find_by(email: params[:email])
出错。在这种情况下,这部分代码返回nil
。所以Rails正试图执行nil.authenticate(params[:password])
。
请检查您的params[:email]
值或用户列表。