3

这是 Rails 4 中为销毁操作自动生成的测试,作为以下规范的一部分vehicles_controller.rb

describe "DELETE destroy" do
     it "destroys the requested vehicle" do
       vehicle = Vehicle.create! valid_attributes
        expect {
          delete :destroy, {:id => vehicle.to_param}, valid_session
        }.to change(Vehicle, :count).by(-1)
     end

    it "redirects to the vehicles list" do
      vehicle = Vehicle.create! valid_attributes
      delete :destroy, {:id => vehicle.to_param}, valid_session
      response.should redirect_to(vehicles_url)
    end
end

这是我在控制器中得到的,同样非常标准:

def destroy
  @vehicle = Vehicle.find(params[:id])
  @vehicle.destroy
  flash[:notice] = "Vehicle has been deleted"
  redirect_to vehicles_url
end

这在应用程序本身中工作得很好——当您删除车辆时,它会重定向回 Vehicles_url,并且该条目会从数据库中删除。服务器日志看起来也完全正常。但是,当我运行规范时,它们失败如下:

1) VehiclesController DELETE destroy destroys the requested vehicle
   Failure/Error: expect {
     count should have been changed by -1, but was changed by 0
   # ./spec/controllers/vehicles_controller_spec.rb:148:in `block (3 levels) in <top (required)>'

2) VehiclesController DELETE destroy redirects to the vehicles list
   Failure/Error: response.should redirect_to(vehicles_url)
     Expected response to be a redirect to <http://test.host/vehicles> but was a redirect to <http://test.host/>.
     Expected "http://test.host/vehicles" to be === "http://test.host/".
   # ./spec/controllers/vehicles_controller_spec.rb:156:in `block (3 levels) in <top (required)>'

谁能指出我这里可能发生了什么导致测试失败?谢谢你的帮助!

编辑:这里有一些关于之前过滤器可能会影响事物的附加信息。在车辆控制器中,由于我使用的是宝石 CanCan,所以我load_and_authorize_resource在顶部。这个控制器也正在测试创建和更新的能力,并且这些规范正在通过,所以我认为这没有干扰,而且它没有因任何与权限有关的消息而失败。也许我需要更改let(:valid_session) { {} }控制器规范顶部的默认设置?我不理会它,因为正如我所说,除了删除之外的所有其他操作都很好。

进一步编辑:根据下面提供的链接,我将我的规范编辑为:

describe "DELETE destroy" do
    it "destroys the requested vehicle" do
      vehicle = Vehicle.create! valid_attributes
      expect {
        delete :destroy, :id => vehicle.to_param, valid_session
      }.to change(Vehicle, :count).by(-1)
    end

    it "redirects to the vehicles list" do
      vehicle = Vehicle.create! valid_attributes
      delete :destroy, :id => vehicle.to_param, valid_session
      response.should redirect_to(vehicles_url)
    end
end

现在,如果我尝试运行规范,我会收到以下语法错误:

/home/kathryn/testing/spec/controllers/vehicles_controller_spec.rb:150: syntax error, unexpected '\n', expecting => (SyntaxError)

第 150 行是指第一个规范中以 开头的行delete :destroy,其中进行了更改。

4

3 回答 3

5

您很可能会遇到授权错误。尝试在任一测试中flash[:alert].should == nil的操作后添加。delete如果您遇到授权问题,您会遇到类似"You are not authorized to access this page."测试失败的情况。

最大的线索是您的测试也失败了:

Expected response to be a redirect to <http://test.host/vehicles> but was a
redirect to <http://test.host/>.

授权失败的典型实现重定向到根路径。

我个人不喜欢, valid_session处理登录的方法。如果您使用的是 Devise,您应该使用他们的测试助手并正确登录。例如

describe VehiclesController do
  include Devise::TestHelpers

  before(:each) do
    sign_in FactoryGirl.create(:user)
  end

  . . .

然后(这很重要!)删除所有参数,否则它们将覆盖设计为您使用该方法, valid_session设置的会话。sign_in

这是最简单的形式;如果某些用户可以(例如)删除而其他用户不能,这仍然会失败,因此对于这些情况,您可能希望创建一个单独的describe "Admin users can" do...end测试块,并与管理员用户before(:each)进行调用。sign_in

我希望这会有所帮助,祝你好运!

于 2013-10-16T19:46:36.040 回答
0

您在将论点传递给delete. 请参阅http://api.rubyonrails.org/classes/ActionController/TestCase/Behavior.html#method-i-delete中的方法定义。

您可以使用:

delete :destroy, {id: vehicle.to_param, session: valid_session}

或者

delete :destroy, id: vehicle:to_param, session: valid_session

我不确定ActionController你传入的最后两个参数内部发生了什么,但它不可能是正确的。

于 2013-10-01T22:31:50.290 回答
0

Ruby 的解析器与内联哈希混淆了。你可能想要:

    delete :destroy, {:id => vehicle.to_param}, valid_session
于 2013-10-02T01:51:18.563 回答