2016-02-04 3 views
1

Мой контрольный тест не проходит. У меня есть before_acton в моем журнале ReviewsController, который проверяет текущего пользователя. Если его нет, он не должен завершить действие create и перенаправить. Но он ее создает, несмотря на то, что сеанс [: user_id] равен нулю. Вот мой код:Контрольный тест не проходит в рельсах

it "doesnt create review if there is valid input, but not authenticated" do 
    video = Video.create(title: "new title", description: "new description") 
    review = Review.create(content: "content1", rating: 1) 
    expect(Review.count).to eq(0) 
end 

В моей ReviewsController:

def create 
    @video = Video.find(params[:video_id]) 
    @review = Review.new(parameters) 
    rating = params[:review][:rating] 
    content = params[:review][:content] 
    @review.content = content 
    @review.rating = rating 
    @review.user_id = current_user.id 
    @review.video = @video 
    @review.save 

    redirect_to @video 
end 

У меня есть before_action в контроллере Обзоры, что проверить, если пользователь прошел проверку подлинности. Если сеанс [: user_id] равен нулю, он перенаправляется на путь sign_in_path. Вот методы:

def current_user 
    @current_user = User.find(session[:user_id]) if session[:user_id] 
end 


def require_user 
    redirect_to sign_in_path unless current_user 
end 

в моем файле reviews_controller_spec.rb, он не должен создать обзор, потому что он не должен пройти мимо before_action: require_user

Почему объект обзора по-прежнему создается ? Почему фильтр before_action не останавливает его? Тест терпит неудачу, и как раз говорит, что ожидается Review.count быть 0, но получил 1.

+3

Вы на самом деле не вызываете своего контроллера в этой спецификации ... просто создаете записи и проверяете, были ли они созданы. – sevenseacat

+0

Я пробовал "сообщение: создать, содержимое:" новый контент ", рейтинг: 3" вместо "review = Review.create (content:" content1 ", рейтинг: 1)", но это дало мне ошибку "Нет маршрутов : action => "create" ", но в моем контроллере есть определенное действие. – joey

+0

Вы создали тестовую базу данных, и данные там создаются? –

ответ

1
# config/routes.rb 
resources :videos, shallow: true do 
    resources :reviews 
end 

Там нет необходимости связывать PARAMS атрибутам 1-1. Фактически это сделает вас контроллерами чрезмерно многословными, а также скучными, как черт, чтобы напечатать его.

class ReviewsController < ApplicationController 

    before_filter :authenticate_user! 

    def create 
    @video = Video.find(params[:video_id]) 
    @review = current_user.reviews.new(review_params) do |r| 
     r.video = @video 
    end 
    end 

    private 
    # this is mass assignment protection 
    def review_params 
     params.require(:review).permit(:rating, :content) 
    end 
end 

Если вы решили свернуть вам собственную проверку подлинности (что это плохая идея) не повторить его через контроллеры и взгляды:

module AuthenticationHelper 
    def current_user 
    @current_user ||= User.find(session[:user_id]) if session[:user_id] 
    end 

    def sign_in(user) 
    @current_user = user 
    session[:user_id] = user.id 
    end 

    def sign_out 
    @current_user = nil 
    reset_session 
    end 

    def authenticate_user! 
    raise User::NotAuthorized unless current_user 
    end 
end 

Ключевым моментом является то, что неавтоматического из модели безопасности гораздо лучше, так как это исключает риск оставить маршрут открытым бездействием:

class ApplicationController 
    include AuthenticationHelper 
    rescue_from User::NotAuthorized, with: :deny_access! 

    # use skip_before_action :authenticate_user! if 
    # you don't want a route/controller to require auth. 
    before_action :authenticate_user! 

    private 
    def deny_access! 
     redirect_to root_path 
    end 
end 

Так, чтобы проверить ReviewsController мы делаем:

describe ReviewsController do 
    let(:user) { User.create(name: 'joe') } 
    let(:video) { Video.create(name: 'Cats Gone Wild') } 
    describe "#create" do 

    let(:valid_attributes) { { video_id: video, title: "new title", description: "new description" } } 

    context "when unauthorized" do 
     it "does not create a review" do 
     expect { post :create, valid_attributes }.to_not change(Review, :count) 
     end 
    end 

    context "when authorized" do 
     before { subject.stub(:current_user) { user } } 

     # ... 
    end 
    end 
end 

Ключевые моменты здесь:

  • использование let зависимостей Тестовое
  • используют expect { action }.to change, чтобы проверить, если это действие изменяет БД. Тестирование на .count == 0 может привести к ложным срабатываниям.
Смежные вопросы