2015-02-08 72 views
0

要学习Rails和测试,我正在使用RSpec(v.3.1.0),Capybara(2.4.3)和FactoryGirl构建Rails 4应用程序。在routes.rb中,我嵌套在以下资源,以反映模型之间的关联:需要帮助解决RSpec控制器测试与嵌套资源

resources :members do 
    resources :cardio_exercises 
end 

members.rb包含: 的has_many:cardio_exercises,:依赖=>:破坏

cardio_exercises.rb包含: belongs_to的:成员

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

嵌套的资源之后,我做了necessa RY修改的意见和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 

我用耙路线的帮助下成功地更新了我的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 

我挣扎写了控制器的测试嵌套资源。目前,“GET index”的测试和“POST create”的第一个测试正在通过;其他测试失败。我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提供所需的信息?我感谢任何帮助!

回答

0

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

错误2是由于has_many未定义关联的单一访问方法(即member.cardio_exercises被定义,但不是member.cardio_exercise)。由于be_a_new只是期望一堂课,你可以简单地通过CardioExercise作为参数。

+0

感谢您的回复。在我最早的机会,我会尝试改变我的控制器规格,并让你知道它是如何发生的。 – codeinspired 2015-02-09 07:09:42

+0

彼得,谢谢!错误2已修复;通过CardioExercise作为参数解决了它。不幸的是,我仍然坚持错误1,3和4.当我通过“:id => @cardio_exercise”它会导致一个记录未找到错误:“无法找到CardioExercise与'id'= 130 [WHERE”cardio_exercises “。”member_id“= $ 1]”。我必须做更多的研究。我不知道为什么无法找到记录或为什么member_id = $ 1。 – codeinspired 2015-02-09 20:06:58

+0

由于这个问题已经得到解答,并且你的新问题构成了一组不同的条件/症状,你应该提交一个单独的问题。 也就是说,您现在面临的问题是,您没有将心脏训练与测试设置中的成员关联,因此'@ member.cardio_exercises'将始终返回控制器中的空集。 – 2015-02-10 04:42:25