2016-09-06 11 views
11

Ich verfolge diese post über die Einrichtung der Authentifizierung in den Routen meiner Rails 4-Anwendung.Authentifizierte Route funktioniert nicht für Rspec-Test

Hier ist meine routes.rb Datei:

Rails.application.routes.draw do 

    devise_for :employees, :controllers => { registrations: 'employees/registrations' } 
    devise_for :clients 


    authenticate :employee do 
    resources :quotation_requests, only: [:show, :edit,:index, :update, :destroy] 
    end 

    resources :quotation_requests, only: [:new, :create] 

    get '/dashboard' => 'dashboard#show', as: 'show_dashboard' 
    root to: 'home#index' 
end 

Hier ist meine quotation_requests_controller_spec.rb Datei:

require 'rails_helper' 

RSpec.describe QuotationRequestsController, type: :controller do 


    describe "GET index" do 
     it "renders :index template" do 
      get :index 
      expect(response).to render_template(:index) 
     end 

     it "assigns quotation requests to template" do 
      quotation_requests = FactoryGirl.create_list(:quotation_request, 3) 
      get :index 
      expect(assigns(:quotation_requests)).to match_array(quotation_requests) 
     end 

    end 

    describe "GET edit" do 
     let(:quotation_request) { FactoryGirl.create(:quotation_request)} 

     it "renders :edit template" do 
      get :edit, id: quotation_request 
      expect(response).to render_template(:edit) 
     end 
     it "assigns the requested quotation request to template" do 
      get :edit, id: quotation_request 
      expect(assigns(:quotation_request)).to eq(quotation_request) 
     end 
    end 

    describe "PUT update" do 
     let(:quotation_request) { FactoryGirl.create(:quotation_request)} 

     context "valid data" do 
      new_text = Faker::Lorem.sentence(word_count=500) 
      let(:valid_data) { FactoryGirl.attributes_for(:quotation_request, sample_text: new_text)} 

      it "redirects to quotation_request#showtemplate" do 
       put :update, id: quotation_request, quotation_request: valid_data 
       expect(response).to redirect_to(quotation_request) 
      end 
      it "updates quotation request in the database" do 
       put :update, id: quotation_request, quotation_request: valid_data 
       quotation_request.reload #need to reload the object because we have just updated it in the database so need to get the new values 
       expect(quotation_request.sample_text).to eq(new_text) 
      end 
     end 

     context "invalid data" do 
      let(:invalid_data) { FactoryGirl.attributes_for(:quotation_request, sample_text: "", number_of_words: 400)} 

      it "renders the :edit template" do 
       put :update, id: quotation_request, quotation_request: invalid_data 
       expect(response).to render_template(:edit) 
      end 
      it "does not update the quotation_request in the database" do 
       put :update, id: quotation_request, quotation_request: invalid_data 
       quotation_request.reload 
       expect(quotation_request.number_of_words).not_to eq(400) 
      end 
     end 
    end 

    describe "GET new", new: true do 
     it "renders :new template" do 
      get :new 
      expect(response).to render_template(:new) 
     end 
     it "assigns new QuotationRequest to @quotation_request" do 
      get :new 
      expect(assigns(:quotation_request)).to be_a_new(QuotationRequest) 
     end 
    end 

    describe "GET show" do 

     #this test requires that there be a quotation request in the database 
     let(:quotation_request) { FactoryGirl.create(:quotation_request) } 

     context 'invalid request' do 

      it "does not render :show template if an employee or client is not signed in" do 

       #setup 
       quotation_request = create(:quotation_request) 

       #exercise 
       get :show, id: quotation_request 

       #verification 
       expect(response).to_not render_template(:show) 

      end 

     end 

     context 'valid request' do 

      sign_in_proofreader 

      it "renders :show template if an employee or client is signed in" do 

       #setup 
       quotation_request = create(:quotation_request) 


       #exercise 
       get :show, id: quotation_request 

       #verification 
       expect(response).to render_template(:show) 
      end 

      it "assigns requested quotation_request to @quotation_request" do 
       get :show, id: quotation_request 
       expect(assigns(:quotation_request)).to eq(quotation_request) 
      end 

     end 
    end 

    describe "POST create", post: true do 
     context "valid data" do 
      let(:valid_data) {FactoryGirl.nested_attributes_for(:quotation_request)} 

      it "redirects to quotation_requests#show" do 
       post :create, quotation_request: valid_data 
       expect(response).to redirect_to(quotation_request_path(assigns[:quotation_request])) 
      end 

      it "creates new quotation_request in database" do 
      expect { 
       post :create, quotation_request: valid_data 
       }.to change(QuotationRequest, :count).by(1) 
      end 
     end 

     context "invalid data" do 
     let(:invalid_data) {FactoryGirl.nested_attributes_for(:quotation_request).merge(sample_text: 'not enough sample text')} 

      it "renders :new template" do 
       post :create, quotation_request: invalid_data 
       expect(response).to render_template(:new) 
      end 

      it "doesn't creates new quotation_request in database" do 
       expect { 
        post :create, quotation_request: invalid_data 
       }.not_to change(QuotationRequest, :count) 
      end 
     end 
    end 

    describe "DELETE destroy" do 

     let(:quotation_request) { FactoryGirl.create(:quotation_request) } 

     it "redirects to the quotation request#index" do 
      delete :destroy, id: quotation_request 
      expect(response).to redirect_to(quotation_requests_path) 
     end 
     it "delets the quotation request from the database" do 
      delete :destroy, id: quotation_request 
      expect(QuotationRequest.exists?(quotation_request.id)).to be_falsy 
     end 

    end 
end 

Mein quotation_requests_controller.rb

class QuotationRequestsController < ApplicationController 
# before_action :authenticate_employee!, :only => [:show] 

    def index 
     @quotation_requests = QuotationRequest.all 
    end 

    def new 
     @quotation_request = QuotationRequest.new 
     @quotation_request.build_client 
    end 

    def edit 
     @quotation_request = QuotationRequest.find(params[:id]) 
    end 

    def create 
     client = Client.find_or_create(quotation_request_params[:client_attributes]) 
     @quotation_request = QuotationRequest.new(quotation_request_params.except(:client_attributes).merge(client: client)) 
     if @quotation_request.save 
     ClientMailer.quotation_request_created(client.email, @quotation_request.id).deliver_now 
     redirect_to @quotation_request, notice: 'Thank you.' 
     else 
     render :new 
     end 
    end 

    def show 
     @quotation_request = QuotationRequest.find(params[:id]) 
    end 

    def update 
     @quotation_request = QuotationRequest.find(params[:id]) 
     if @quotation_request.update(quotation_request_params) 
      redirect_to @quotation_request 
     else 
      render :edit 
     end 
    end 

    def destroy 
     QuotationRequest.destroy(params[:id]) 
     redirect_to quotation_requests_path 
    end 

    private 

    def quotation_request_params 
     params.require(:quotation_request).permit(:number_of_words, :return_date, :sample_text, :client_attributes => [:first_name, :last_name, :email]) 
    end 

end 

ich die Routen-Authentifizierung kennen funktioniert, weil, wenn ich sie im Browser teste ich auf das Zeichen_ weitergeleitet werde auf Seite. Die Tests geben Rspec jedoch nicht weiter.

wenn ich diesen Code in das quotation_requests_controller.rb setzen:

before_action :authenticate_employee!, :only => [:show] 

Die rspec Tests bestehen. Aus irgendeinem Grund registriert Rspec die Authentifizierung der Routen nicht.

Hier ist die Ausgabe von Rspec für die Tests mit den authentifizierten Routen laufen:

QuotationRequestsController 
    GET index 
    valid request 
     renders :index template for signed in employee 
     assigns quotation requests to template 
    invalid request 
     does not render :index template without a signed in employee (FAILED - 1) 
    GET edit 
    valid request 
     renders :edit template with a signed in employee 
     assigns the requested quotation request to template 
    invalid request 
     does not render the :edit template without a signed in employee (FAILED - 2) 
    PUT update 
    valid request 
     valid data 
     redirects to quotation_request#showtemplate 
     updates quotation request in the database 
     invalid data 
     renders the :edit template 
     does not update the quotation_request in the database 
    invalid request 
     redirects user to the sign in page (FAILED - 3) 
    GET new 
    renders :new template 
    assigns new QuotationRequest to @quotation_request 
    GET show 
    invalid request 
     does not render :show template if an employee or client is not signed in (FAILED - 4) 
    valid request 
     renders :show template if an employee or client is signed in 
     assigns requested quotation_request to @quotation_request 
    POST create 
    valid data 
     redirects to quotation_requests#show 
     creates new quotation_request in database 
    invalid data 
     renders :new template 
     doesn't creates new quotation_request in database 
    DELETE destroy 
    valid request 
     redirects to the quotation request#index 
     delets the quotation request from the database 
    invalid request 
     does not delete the quotation request without a signed in employee (FAILED - 5) 

Failures: 

    1) QuotationRequestsController GET index invalid request does not render :index template without a signed in employee 
    Failure/Error: expect(response).to_not render_template(:index) 
     Didn't expect to render index 
    # ./spec/controllers/quotation_requests_controller_spec.rb:43:in `block (4 levels) in <top (required)>' 
    # -e:1:in `<main>' 

    2) QuotationRequestsController GET edit invalid request does not render the :edit template without a signed in employee 
    Failure/Error: expect(response).to_not render_template(:edit) 
     Didn't expect to render edit 
    # ./spec/controllers/quotation_requests_controller_spec.rb:92:in `block (4 levels) in <top (required)>' 
    # -e:1:in `<main>' 

    3) QuotationRequestsController PUT update invalid request redirects user to the sign in page 
    Failure/Error: expect(response).to_not redirect_to(quotation_request) 
     Didn't expect to redirect to #<QuotationRequest:0x007fe7eb69c8c0> 
    # ./spec/controllers/quotation_requests_controller_spec.rb:182:in `block (4 levels) in <top (required)>' 
    # -e:1:in `<main>' 

    4) QuotationRequestsController GET show invalid request does not render :show template if an employee or client is not signed in 
    Failure/Error: expect(response).to_not render_template(:show) 
     Didn't expect to render show 
    # ./spec/controllers/quotation_requests_controller_spec.rb:217:in `block (4 levels) in <top (required)>' 
    # -e:1:in `<main>' 

    5) QuotationRequestsController DELETE destroy invalid request does not delete the quotation request without a signed in employee 
    Failure/Error: expect(QuotationRequest.exists?(quotation_request.id)).to be_truthy 

     expected: truthy value 
      got: false 
    # ./spec/controllers/quotation_requests_controller_spec.rb:361:in `block (4 levels) in <top (required)>' 
    # -e:1:in `<main>' 

Finished in 2.11 seconds (files took 1.75 seconds to load) 
23 examples, 5 failures 

Failed examples: 

rspec ./spec/controllers/quotation_requests_controller_spec.rb:37 # QuotationRequestsController GET index invalid request does not render :index template without a signed in employee 
rspec ./spec/controllers/quotation_requests_controller_spec.rb:83 # QuotationRequestsController GET edit invalid request does not render the :edit template without a signed in employee 
rspec ./spec/controllers/quotation_requests_controller_spec.rb:171 # QuotationRequestsController PUT update invalid request redirects user to the sign in page 
rspec ./spec/controllers/quotation_requests_controller_spec.rb:208 # QuotationRequestsController GET show invalid request does not render :show template if an employee or client is not signed in 
rspec ./spec/cont 

Warum haben die Routen ich geschrieben habe, nicht in Rspec Tests funktionieren?

+0

Bitte geben Sie die Ausgabe von rspec run an. – dodo121

Antwort

2

Ich nehme an, Sie verwenden rspec-rails in Ihrer Schiene App. Rspec-rails richtet für dich eine Menge an Komfortmethoden ein, bringt aber auch etwas Schwarzmagie mit sich, was zu einigen unerwarteten Ergebnissen führen kann - so.

As you can see here es in den Kommentaren für Controller-Spezifikationen erklärt:

# Supports a simple DSL for specifying behavior of ApplicationController. 
# Creates an anonymous subclass of ApplicationController and evals the 
# `body` in that context. Also sets up implicit routes for this 
# controller, that are separate from those defined in "config/routes.rb". 

ich die Logik ist hier erraten, sind Controller-Funktionen aus den Bereichen Routing unterschiedlich und sollten getrennt (und in der Tat rspec-Schienen bieten eine Testgruppe getestet werden für Routing), so dass wir die Routen für die Controller-Spezifikationen nicht benötigen, was bedeutet, dass Sie in der Lage sein sollten, Ihren Controller zu testen, ohne die Routen einzurichten.

Meiner Meinung nach ist das Testen der Weiterleitung für nicht authentifizierte Benutzer eher ein Integrationstest, da mehrere Teile Ihrer Anwendung zusammenarbeiten müssen und als solche nicht im Controllerkontext getestet werden sollten, sondern eher als Feature in etwas Blackbox-Test.

Sie können sie in einem dieser Verzeichnisse spec/requests, spec/api, and spec/integration oder explizit erklärt ihre Art mit

RSpec.describe "Something", type: :request do 

oder legen Sie es in spec/features oder erklären den Typ als

RSpec.describe "Something", type: :feature do 

Platzierung Integrationstests schreiben, indem je Auf welcher Ebene möchten Sie die Weiterleitung testen (dh nur den Anfrage-Antwort-Zyklus testen oder in einem simulierten Browser ausführen). Weitere Informationen finden Sie in der Dokumentation für Integrationstests unter rspec-rails github page.

+0

Vielen Dank für die Klärung. Jetzt kann ich die Authentifizierung innerhalb der Routen implementieren, wo sie sein sollte. – chell

Verwandte Themen