需要帮助使用嵌套资源排除RSpec控制器测试故障

时间:2015-02-08 21:23:59

标签: ruby-on-rails testing rspec

为了学习Rails和测试,我使用RSpec(v.3.1.0),Capybara(2.4.3)和FactoryGirl构建了一个Rails 4应用程序。在routes.rb中,我嵌套了以下资源以反映模型之间的关联:

resources :members do
  resources :cardio_exercises
end

members.rb包含:      has_many:cardio_exercises,:dependent => :破坏

cardio_exercises.rb包含:      belongs_to:member

有关cardio_exercises的FactoryGirl工厂包含     协会:会员

在嵌套资源之后,我对视图和cardio_exercises_controller.rb进行了必要的更改:

class CardioExercisesController < ApplicationController

# :get_member is defined in the private method at the bottom of this file,
# and takes the member_id provided by the routing and
#converts it to a @member object.

before_action :get_member    

# GET member/1/cardio_exercises
# GET member/1/cardio_exercises.json
def index
  @cardio_exercises = @member.cardio_exercises
end

# GET member/1/cardio_exercises/1
# GET member/1/cardio_exercises/1.json
def show
  @cardio_exercise = @member.cardio_exercises.find(params[:id])
end

# GET member/1/cardio_exercises/new
def new
  @member = Member.find(params[:member_id])
  @cardio_exercise = @member.cardio_exercises.build
end

# GET member/1/cardio_exercises/1/edit
def edit
  @cardio_exercise = @member.cardio_exercises.find(params[:id])
end

# POST member/1/cardio_exercises
# POST member/1/cardio_exercises.json
def create
  @cardio_exercise = @member.cardio_exercises.build(cardio_exercise_params)

  if @cardio_exercise.save
    flash[:success] = "Cardio exercise was successfully created."
    redirect_to member_cardio_exercises_path(@member)
  else
    render 'new'
  end
end  

# PATCH/PUT member/1/cardio_exercises/1
# PATCH/PUT member/1/cardio_exercises/1.json
def update
  @cardio_exercise = @member.cardio_exercises.find(params[:id])
  if @cardio_exercise.update(cardio_exercise_params)
    flash[:success] = "Cardio exercise was successfully updated."
    redirect_to member_cardio_exercises_path(@member)
  else
    render 'edit'
  end
end

# DELETE member/1/cardio_exercises/1
# DELETE member/1/cardio_exercises/1.json
def destroy
  @cardio_exercise = @member.cardio_exercises.find(params[:id])
  @cardio_exercise.destroy
  respond_to do |format|
    format.html { redirect_to (member_cardio_exercises_path(@member)), notice: 'Cardio exercise was successfully destroyed.' }
    format.json { head :no_content }
  end
 end


private
  # The get_member action converts the member_id given by the routing
  # into an @member object, for use here and in the view.

  def get_member
    @member = Member.find(params[:member_id])
  end


  def cardio_exercise_params
    params.require(:cardio_exercise).permit(:title, :duration, :calories_burned, :date, :member_id)
  end
end

我在rake路由的帮助下成功更新了我的RSpec路由测试:

                 Prefix Verb   URI Pattern                                             Controller#Action
                   root GET    /                                                       static_pages#home
                  about GET    /about(.:format)                                        static_pages#about
                   help GET    /help(.:format)                                         static_pages#help
                contact GET    /contact(.:format)                                      static_pages#contact
                 signup GET    /signup(.:format)                                       users#new
                  login GET    /login(.:format)                                        sessions#new
                        POST   /login(.:format)                                        sessions#create
                 logout DELETE /logout(.:format)                                       sessions#destroy
                  users GET    /users(.:format)                                        users#index
                        POST   /users(.:format)                                        users#create
               new_user GET    /users/new(.:format)                                    users#new
              edit_user GET    /users/:id/edit(.:format)                               users#edit
                   user GET    /users/:id(.:format)                                    users#show
                        PATCH  /users/:id(.:format)                                    users#update
                        PUT    /users/:id(.:format)                                    users#update
                        DELETE /users/:id(.:format)                                    users#destroy
member_cardio_exercises GET    /members/:member_id/cardio_exercises(.:format)          cardio_exercises#index
                        POST   /members/:member_id/cardio_exercises(.:format)          cardio_exercises#create
new_member_cardio_exercise GET    /members/:member_id/cardio_exercises/new(.:format)      cardio_exercises#new
edit_member_cardio_exercise GET    /members/:member_id/cardio_exercises/:id/edit(.:format) cardio_exercises#edit
 member_cardio_exercise GET    /members/:member_id/cardio_exercises/:id(.:format)      cardio_exercises#show
                        PATCH  /members/:member_id/cardio_exercises/:id(.:format)      cardio_exercises#update
                        PUT    /members/:member_id/cardio_exercises/:id(.:format)      cardio_exercises#update
                        DELETE /members/:member_id/cardio_exercises/:id(.:format)      cardio_exercises#destroy
                members GET    /members(.:format)                                      members#index
                        POST   /members(.:format)                                      members#create
             new_member GET    /members/new(.:format)                                  members#new
            edit_member GET    /members/:id/edit(.:format)                             members#edit
                 member GET    /members/:id(.:format)                                  members#show
                        PATCH  /members/:id(.:format)                                  members#update
                        PUT    /members/:id(.:format)                                  members#update
                        DELETE /members/:id(.:format)                                  members#destroy
               trainers GET    /trainers(.:format)                                     trainers#index
                        POST   /trainers(.:format)                                     trainers#create
            new_trainer GET    /trainers/new(.:format)                                 trainers#new
           edit_trainer GET    /trainers/:id/edit(.:format)                            trainers#edit
                trainer GET    /trainers/:id(.:format)                                 trainers#show
                        PATCH  /trainers/:id(.:format)                                 trainers#update
                        PUT    /trainers/:id(.:format)                                 trainers#update
                        DELETE /trainers/:id(.:format)                                 trainers#destroy
     strength_exercises GET    /strength_exercises(.:format)                           strength_exercises#index
                        POST   /strength_exercises(.:format)                           strength_exercises#create
  new_strength_exercise GET    /strength_exercises/new(.:format)                       strength_exercises#new
 edit_strength_exercise GET    /strength_exercises/:id/edit(.:format)                  strength_exercises#edit
      strength_exercise GET    /strength_exercises/:id(.:format)                       strength_exercises#show
                        PATCH  /strength_exercises/:id(.:format)                       strength_exercises#update
                        PUT    /strength_exercises/:id(.:format)                       strength_exercises#update
                        DELETE /strength_exercises/:id(.:format)                       strength_exercises#destroy
           appointments GET    /appointments(.:format)                                 appointments#index
                        POST   /appointments(.:format)                                 appointments#create
        new_appointment GET    /appointments/new(.:format)                             appointments#new
       edit_appointment GET    /appointments/:id/edit(.:format)                        appointments#edit
            appointment GET    /appointments/:id(.:format)                             appointments#show
                        PATCH  /appointments/:id(.:format)                             appointments#update
                        PUT    /appointments/:id(.:format)                             appointments#update
                        DELETE /appointments/:id(.:format)                             appointments#destroy

我正在努力为嵌套资源编写控制器测试。目前,测试&#34; GET指数&#34;和(#第一个)&#34; POST create&#34;正在经过;其他测试都失败了。我的cardio_exercises_controller_spec.rb不完整,但到目前为止我还有:

require 'rails_helper'

RSpec.describe CardioExercisesController, :type => :controller do
before :each do
  @member = FactoryGirl.create(:member)
  @cardio_exercise = FactoryGirl.create(:cardio_exercise)
  @cardio_exercise_attributes = FactoryGirl.attributes_for(:cardio_exercise, :member_id => @member)
end

describe "GET index" do
  it "assigns all cardio_exercises as @member.cardio_exercises" do     
    get :index, { :member_id => @member  }
    expect(assigns(:cardio_exercises)).to eq(@member.cardio_exercises)
  end
end

describe "GET show" do
  it "assigns the requested cardio_exercise as @member.cardio_exercise" do
    #@cardio_exercise = @member.cardio_exercises.find(params[:id])      
    get :show, { :member_id => @member, :cardio_exercise_id => @cardio_exercise }
    expect(assigns(:cardio_exercise)).to eq(@member.cardio_exercise)
  end
end 

describe "GET new" do
  it "assigns a new cardio_exercise as @member.cardio_exercise" do
    get :new, { :member_id => @member }
    expect(assigns(:cardio_exercise)).to be_a_new(@member.cardio_exercise)
  end
end

describe "GET edit" do
  xit "assigns the requested cardio_exercise as @member.cardio_exercise" do 
  end
end

describe "POST create" do
  describe "with valid params" do
    it "creates a new CardioExercise" do
      expect {
                  post :create, { :member_id => @member, :cardio_exercise => @cardio_exercise_attributes }
      }.to change(CardioExercise, :count).by(1)         
    end

    xit "assigns a newly created cardio_exercise as @cardio_exercise" do
    end

    xit "redirects to the created cardio_exercise" do
    end
  end
end

describe "PUT update" do
    describe "with invalid params" do

    xit "updates the requested cardio_exercise" do

   end

   xit "assigns the requested cardio_exercise as @member.cardio_exercise" do

   end

    xit "redirects to the cardio_exercise" do
   end
  end

  describe "with invalid params" do
    xit "assigns the cardio_exercise as @member.cardio_exercise" do

  end

  xit "re-renders the 'edit' template" do

    expect(response).to render_template("edit")
    end
  end
end

describe "DELETE destroy" do
  it "destroys the requested cardio_exercise" do
    expect {
      delete :destroy, { :member_id => @member, :cardio_exercise_id => @cardio_exercise }
    }.to change(CardioExercise, :count).by(-1)
  end

  it "redirects to the cardio_exercises list" do      
    delete :destroy, { :member_id => @member, :cardio_exercise_id => @cardio_exercise }
    expect(response).to redirect_to(member_cardio_exercises_url)
  end
 end
end

运行规范不会产生路由匹配和未定义的方法错误:

1) CardioExercisesController GET show assigns the requested cardio_exercise as @member.cardio_exercise
 Failure/Error: get :show, { :member_id => @member, :cardio_exercise_id => @cardio_exercise }
 ActionController::UrlGenerationError:
   No route matches {:action=>"show", :cardio_exercise_id=>"15", :controller=>"cardio_exercises", :member_id=>"29"}

2) CardioExercisesController GET new assigns a new cardio_exercise as @member.cardio_exercise
 Failure/Error: expect(assigns(:cardio_exercise)).to be_a_new(@member.cardio_exercise)
 NoMethodError:
   undefined method `cardio_exercise' for #<Member:0x00000009aaa628>

3) CardioExercisesController DELETE destroy destroys the requested cardio_exercise
 Failure/Error: delete :destroy, { :member_id => @member, :cardio_exercise_id => @cardio_exercise }
 ActionController::UrlGenerationError:
   No route matches {:action=>"destroy", :cardio_exercise_id=>"18", :controller=>"cardio_exercises", :member_id=>"35"}

 4) CardioExercisesController DELETE destroy redirects to the cardio_exercises list
 Failure/Error: delete :destroy, { :member_id => @member, :cardio_exercise_id => @cardio_exercise }
 ActionController::UrlGenerationError:
   No route matches {:action=>"destroy", :cardio_exercise_id=>"19", :controller=>"cardio_exercises", :member_id=>"37"}

嵌套路由和相关视图代码在我的应用程序中按预期工作。显然,我没有给RSpec提供测试控制器所需的所有信息。我知道我必须通过id进行一些测试,但我对语法感到困惑。在我的研究过程中,我发现了许多讨论这个问题的帖子,但我没有用它来解决它。

如何更改控制器测试以向RSpec提供所需的信息?我感谢任何帮助!

1 个答案:

答案 0 :(得分:0)

错误1,3和4是由于您的RSpec示例正在设置参数:cardio_exercise_id而不是所需的(根据您的路线):id。您传递的示例正在运行,因为他们不需要此参数。

错误2是由于has_many没有为关联定义单一访问方法(即member.cardio_exercises已定义,但不是member.cardio_exercise)。由于be_a_new只需要一个类,因此您只需将CardioExercise作为参数传递。