要学习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提供所需的信息?我感谢任何帮助!
感谢您的回复。在我最早的机会,我会尝试改变我的控制器规格,并让你知道它是如何发生的。 – codeinspired 2015-02-09 07:09:42
彼得,谢谢!错误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
由于这个问题已经得到解答,并且你的新问题构成了一组不同的条件/症状,你应该提交一个单独的问题。 也就是说,您现在面临的问题是,您没有将心脏训练与测试设置中的成员关联,因此'@ member.cardio_exercises'将始终返回控制器中的空集。 – 2015-02-10 04:42:25