Ruby on rails lambda do count应更改为1,但已更改为0

Ruby on rails lambda do count应更改为1,但已更改为0,ruby-on-rails,rspec,lambda,Ruby On Rails,Rspec,Lambda,我正在测试我的应用程序以创建一辆新的用户汽车,之后用户创建了一辆新汽车,应用程序必须重定向到我发布路线的用户车路径: user_cars GET /users/:user_id/cars(.:format) cars#index POST /users/:user_id/cars(.:format) cars#create

我正在测试我的应用程序以创建一辆新的用户汽车,之后用户创建了一辆新汽车,应用程序必须重定向到我发布路线的用户车路径:

user_cars GET    /users/:user_id/cars(.:format)                               cars#index
                      POST   /users/:user_id/cars(.:format)                               cars#create
         new_user_car GET    /users/:user_id/cars/new(.:format)                           cars#new
        edit_user_car GET    /users/:user_id/cars/:id/edit(.:format)                      cars#edit
             user_car GET    /users/:user_id/cars/:id(.:format)                           cars#show
                      PUT    /users/:user_id/cars/:id(.:format)                           cars#update
                      DELETE /users/:user_id/cars/:id(.:format)                           cars#destroy
因此,我正在使用以下rspec测试我的应用程序:

describe "POST 'create' car" do

describe "car created success" do
  before(:each) do
            @user = User.create!(:email => "foo@example.com", :password => "foobar", :password_confirmation => "foobar" )
            @car = Car.create!(:brand => "example", :color => "foobar", :model => "foobar", :year =>"2012")
  end

  it "should create a car" do
    lambda do
      post :create, :cars => @car, :user_id => @user.id
    end.should change(Car, :count).by(1)
  end

  it "should redirect to the user cars page" do
    post :create, :cars => @car, :user_id => @user.id
    response.should redirect_to user_car_path(@user, @car)
  end
end
end
但是我犯了两个错误

Failures:

1) CarsController POST 'create' car car created success should create a car
 Failure/Error: lambda do
   count should have been changed by 1, but was changed by 0
 # ./spec/controllers/car_controller_spec.rb:20

2) CarsController POST 'create' car car created success should redirect to the user cars page
 Failure/Error: response.should redirect_to user_car_path(@user, @car)
   Expected response to be a redirect to <http://test.host/users/115/cars/40> but was a redirect to <http://test.host/users/115/cars/new>.
 # ./spec/controllers/car_controller_spec.rb:27
但我的应用程序工作正常;这是我的汽车控制器

class CarsController < ApplicationController
....

def create
  @user = User.find(params[:user_id])
  @car = @user.cars.build(params[:car])
  if @car.save
    redirect_to user_car_path(@user, @car), :flash => { :notice => "  car created!" }
  else
    redirect_to new_user_car_path ,:flash => { :notice => " sorry try again :(" }
  end
end
def show
  @user = User.find(params[:user_id])     
  @car = @user.cars.find(params[:id])   
end

....

我认为您需要以下内容:cars=>:car并使用参数,使控制器中的car创建有效。我不明白你为什么要在你的规格中创造汽车,因为这似乎是对汽车创造的测试

  it "should create a car" do
    lambda do
      post :create, :car => {:brand => "example", :color => "foobar", :model => "foobar", :year =>"2012"}, :user_id => @user.id
    end.should change(Car, :count).by(1)
  end

  it "should redirect to the user cars page" do
    post :create, :car => {:brand => "example", :color => "foobar", :model => "foobar", :year =>"2012"}, :user_id => @user.id
    response.should redirect_to user_car_path(@user, @car)
  end

我认为您需要以下内容:cars=>:car并使用参数,使控制器中的car创建有效。我不明白你为什么要在你的规格中创造汽车,因为这似乎是对汽车创造的测试

  it "should create a car" do
    lambda do
      post :create, :car => {:brand => "example", :color => "foobar", :model => "foobar", :year =>"2012"}, :user_id => @user.id
    end.should change(Car, :count).by(1)
  end

  it "should redirect to the user cars page" do
    post :create, :car => {:brand => "example", :color => "foobar", :model => "foobar", :year =>"2012"}, :user_id => @user.id
    response.should redirect_to user_car_path(@user, @car)
  end

我想这是因为你的验证失败了。要知道它是否失败,请在保存到控制器之前执行以下操作:

puts @car.valid?
如果它是错误的,你的测试将失败,这是正常的。要设置为true,可以执行以下操作:

before(:each) do
  ...
  Car.any_instance.stub(:valid?).and_return(true)
end

您还可以使用存根和模拟来返回User.find和Car.build的实例。查看文档:

我认为这是因为验证失败。要知道它是否失败,请在保存到控制器之前执行以下操作:

puts @car.valid?
如果它是错误的,你的测试将失败,这是正常的。要设置为true,可以执行以下操作:

before(:each) do
  ...
  Car.any_instance.stub(:valid?).and_return(true)
end

您还可以使用存根和模拟来返回User.find和Car.build的实例。请参阅文档:

您正在数据库中创建汽车,而不仅仅是在before:each中创建汽车对象。此外,您将参数传递为:cars,而不是:car。最后,我个人也会使用let。试试这个

describe "POST 'create' car" do

  let(:user) { User.create!(:email => "foo@example.com", :password => "foobar", :password_confirmation => "foobar" ) }
  let(:car)  { Car.new(:brand => "example", :color => "foobar", :model => "foobar", :year =>"2012")}

  it "should create a car" do
    lambda do
      post :create, :car => car, :user_id => user.id
    end.should change(Car, :count).by(1)
  end

  it "should redirect to the user cars page" do
    post :create, :cars => car, :user_id => user.id
    # note: car doesn't have an ID, you have to fetch it from the db to get an id
    response.should redirect_to user_car_path(user.id, user.cars.last.id)
  end
end
作为最后一点,您将要研究

然后你可以这样做:

let(:user){ FactoryGirl.create(:user) }
let(:car) { FactoryGirl.build(:car) } # note: BUILD not CREATE

您正在数据库中创建汽车,而不仅仅是在before:each中创建汽车对象。此外,您将参数传递为:cars,而不是:car。最后,我个人也会使用let。试试这个

describe "POST 'create' car" do

  let(:user) { User.create!(:email => "foo@example.com", :password => "foobar", :password_confirmation => "foobar" ) }
  let(:car)  { Car.new(:brand => "example", :color => "foobar", :model => "foobar", :year =>"2012")}

  it "should create a car" do
    lambda do
      post :create, :car => car, :user_id => user.id
    end.should change(Car, :count).by(1)
  end

  it "should redirect to the user cars page" do
    post :create, :cars => car, :user_id => user.id
    # note: car doesn't have an ID, you have to fetch it from the db to get an id
    response.should redirect_to user_car_path(user.id, user.cars.last.id)
  end
end
作为最后一点,您将要研究

然后你可以这样做:

let(:user){ FactoryGirl.create(:user) }
let(:car) { FactoryGirl.build(:car) } # note: BUILD not CREATE


您已经创建了该车,并在之前的步骤中将其保存到数据库中,因此我猜不会再次创建该车。尝试使用@car=car.new。。。而不是@car=car.create!。。。谢谢你的回答,你能给我解释清楚吗?我在哪里造的车?我刚开始学英语rspec@Asantoya17自己查看代码中的@car=car.create!另外,阅读rails文档并找出创建的原因!它不同于新的。这不是rspec问题。我更改了它,但现在出现以下错误:失败/错误:响应。是否应该操作控制器::路由错误:没有匹配的路由{:action=>show,:user\u id=>,:controller=>cars这意味着您的@car.save现在返回true,您的重定向到user\u car\u路径有问题…行您已经创建了该车,并在之前的步骤中将其保存到数据库中,因此我猜不会再次创建它。尝试使用@car=car.new…而不是@car=car.create!…a谢谢你的回答,你能给我解释清楚一点吗?我是在哪里造的车?我从哪里开始的rspec@Asantoya17自己查看代码中的@car=car.create!另外,阅读rails文档,找出为什么create!与new不同。这不是rspec的事情。我更改了它,但现在出现了以下错误:Failure/错误:response.should ActionController::RoutingError:没有路由匹配{:action=>show,:user\u id=>,:controller=>cars这意味着你的@car.save现在返回true,你的重定向到user\u car\u路径有问题…line真的我在学习rspec也许这就是我可能会出错的原因我在学习rspec也许这就是我可能会出错的原因我解决了第一个错误,但仍然出现了第二个错误rs预期的响应是重定向到,但重定向是尝试在测试中删除car的“s”。尝试在控制器中添加puts@car和puts@user以检查它们是否为零。例如,您也可以使用pry在控制器中进入调试模式。错误更改为ActionController::RoutingError::action=>show,:controller=>cars这个答案只会给你带来新的问题。你正在短路正常的Rails行为,并强迫@cars.save在正常情况下返回true。不要这样做。我不同意。你想在成功保存汽车时测试你的行为。使用存根,这正是你正在做的。这是隔离!好的,我解决了第一个问题错误,但第二个错误仍然出现。预期响应是重定向到,但重定向是尝试在测试中删除car的“s”。尝试在控制器中添加puts@car,并将@user放入以检查它们是否为零。例如,您也可以在控制器中使用pry进入调试模式。错误更改为ActionController::RoutiNgeror::action=>show,:controller=>cars此答案只会给您带来新问题。您正在使Rails的正常行为短路,并强制@cars.save返回true
通常不会的时候。不要这样做,我不同意。当车辆成功保存时,您希望测试您的操作行为。有了存根,这就是你正在做的。这是隔离@Asantoya17“什么都没有”是什么意思?它不会显示相同的错误,现在出现ActionController::RoutingError::action=>show,:controller=>carsSo我的答案修复了您的第一个问题,但您还有另一个问题。尝试重定向到用户车_path@user.id,@car.idI希望您耐心等待,它显示了另一个错误…称为nil的id,错误为4-如果您确实想要nil的id,请使用object_id现在您必须找出@user是nil还是@car是nil,并确定原因。等待->错误发生在哪里?另外,请参见我的第二次编辑spec@Asantoya17“什么都没有”是什么意思?它不会显示相同的错误,现在出现ActionController::RoutingError::action=>show,:controller=>carsSo我的答案修复了您的第一个问题,但您还有另一个问题。尝试重定向到用户车_path@user.id,@car.idI希望您耐心等待,它显示了另一个错误…称为nil的id,错误为4-如果您确实想要nil的id,请使用object_id现在您必须找出@user是nil还是@car是nil,并确定原因。等待->错误发生在哪里?另外,请参见我对第二个等级库的编辑