Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/58.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 为控制器中的删除操作编写rspec测试_Ruby On Rails_Ruby_Rspec_Factory Bot - Fatal编程技术网

Ruby on rails 为控制器中的删除操作编写rspec测试

Ruby on rails 为控制器中的删除操作编写rspec测试,ruby-on-rails,ruby,rspec,factory-bot,Ruby On Rails,Ruby,Rspec,Factory Bot,我的一个控制器中有一个删除功能,如下所示: before_action :set_form, only: [:show, :edit, :update, :destroy] def destroy if @form.destroy render json: @form, status: :ok else render json: @form.errors, status: :not_found end

我的一个控制器中有一个删除功能,如下所示:

before_action :set_form, only: [:show, :edit, :update, :destroy]
 def destroy
    if @form.destroy
            render json: @form, status: :ok
        else
            render json: @form.errors, status: :not_found
        end
  end

 private

  def set_form
    @form = Form.find(params[:id])
  end

 end
我有两个问题:

1) 当删除未正确执行时,我返回404。这是合理的身份代码吗?我查看了所有4XX状态代码,这是最有意义的

2) 我不确定如何为
呈现json:@form.errors,status::not_found
编写测试

以下是我尝试过的:

context "Cannot delete the model" do
    it "responds successfully with an HTTP 404 status code" do
        delete :destroy, id: 100000
        expect(response).to have_http_status(404)
    end
end

问题是,我得到一个错误,说
ActiveRecord::RecordNotFound:找不到'id'=10000的Visa,而不是
delete
操作实际失败。如何模拟
delete
操作失败?

该错误与您在开发甚至生产中会遇到的错误相同。那条线

@form = Form.find(params[:id])
如果未找到带有已传递ID的
表单
记录,将引发异常

另外,如果未找到
@form
并且您找到了继续的机制,则
@form.destroy
仍将不工作,因为
nil
对象上没有方法
destroy
,而
nil
对象上也没有方法
错误

如果你坚持按照你描述的方式处理销毁方法,你需要做一些事情,比如

before_action :set_form, only: [:show, :edit, :update] #remove destroy
def destroy
  @form = Form.find_by(id: params[:id])
  if @form
    @form.destroy
    render json: @form, status: :ok
  else
    render json: 'record not found for delete', status: :not_found
  end
end

您的
set\u form
方法会引发该错误,您必须在那里捕获该错误,或者在
destroy
中使用
find\u by\u id

def set_form
  @form = Form.find(params[:id])
rescue ActiveRecord::RecordNotFound
end
这样,
@表单
将在
if
中成为
nil


关于HTTP状态代码,您可以考虑使用.< /p>

Rails将引发<代码> ActureCordR::当调用“代码>”时,记录NOT/<代码>。在具有无效ID的记录上查找“< /代码>”。这是一个非常理想的行为,因为它在找不到资源时提供了一个很好的捕获。 默认情况下,发送404-notfound头。对于HTML请求类型,它还发送一个默认错误页

相反,问题在于如何测试它

如果要测试rails是否引发错误:

context "Cannot delete the model" do
  it "raises an error when the id is not valid" do
    bypass_rescue
    expect { delete :destroy, id: 100000 }.to raise_error(ActiveRecord::RecordNotFound)
    expect(response).to have_http_status(404)
  end
end
但是,如果您想测试删除模型是否因任何其他原因(例如记录被锁定或用户未经授权)而失败,则应在数据库中设置一条带有装置或工厂的记录,并提供有效id-还应提供正确的响应代码(422或401)


至于模拟删除失败,您可以使用
允许(SomeModel.)的任何实例接收(:destroy)。并返回(false)

是否
营救ActiveRecord::RecordNotFound
如果找不到它,只返回@form为nil?这是不是被认为是一种骇客的方式?以前从未遇到过这种情况,因此我很想了解更多关于这种方法的信息。它正在抢救异常,但什么也不做(对于
开始抢救结束
块,a
def
是隐式的
begin
)。实例变量总是初始化为
nil
。我只是想告诉你,问题是,你当然也可以在
destroy
中进行救援,并将
render json:@form.errors,status::not_found
位放在那里。这引发了另一个问题。当
destroy
操作失败时,如何进行测试?如何在rspec中模拟此行为以测试
呈现json:@form.errors,status::not_found
?而且
destroy
函数甚至需要执行错误处理吗?
allow(Form).接收(:find).和提高(ActiveRecord::RecordNotFound)
例如:我承认该部分。我真正想问的是如何测试
render json:@form.errors,status::not_found
part。当我运行simple cov时,我看到rspec没有涵盖该部分。我想投保,这样我可以100%投保。但我不知道如何测试它,因为我不知道如何使
销毁
故意失败。仍然返回
ActiveRecord::RecordNotFound
?不,
find
将引发,
find\u by
将返回
nil
。是的,MichaelKohl说了什么。Michael的答案是好的,但您需要准备好在大多数CRUD方法中接收nil对象的可能性
:show
:edit
:update
,除非您在
应用程序控制器
中为
ActiveRecord::RecordNotFound
添加一个通用的
结果。并不是说这是一条路,但我在几个Rails项目中都看到过。是的,我也看到过同样的情况。但他必须再次在所有方法中处理
@form
可能是
nil
对象的情况。不过,我认为OP还没有准备好调查这种可能性。您介意提供一个额外的测试示例,包括
render json:@form.errors,status::not_found
?假设我找到了一个有效的模型。然而,
destroy
函数由于某种原因失败,并点击了我写的上面一行。如何在rspec中测试此案例?另外,如果我按照你的样本测试,我会得到200分。我还从您的示例中获得了
200
允许(SomeModel.)的任何实例接收(:destroy)。并返回(false)
。如果您能回答我的上述问题,我将不胜感激!