rspec - 如何测试 ActiveRecord::RecordNotFound?

Mei*_*lan 2 ruby unit-testing rspec ruby-on-rails

我有一个方法可以更新人的属性,ActiveRecord::RecordNotFound如果找不到人的话它还有救。方法是:

  def update
    @people= People.find(params[:id])
    if @people.update(people_params)
      render json: { success: 'Success' }
    else
      render :edit
    end
  rescue ActiveRecord::RecordNotFound => e
    render json: { error: 'Failed') }
  end
Run Code Online (Sandbox Code Playgroud)

我想测试一下找不到记录时的情况,这是我现在的测试:

    let(:people) { create(:people) }
    let(:people_id) { people.id }
    let(:user) { people}
    # Other tests...
    context 'when person not found' do
      let(:exception) { ActiveRecord::RecordNotFound }

      # What should I write so that I can let the record not been found?

      before { allow(People).to receive(:find).and_raise(exception) }

      it 'responds with json containing the error message' do
        expect(JSON.parse(response.body)).to eq({error:'Error'})
      end
    end
Run Code Online (Sandbox Code Playgroud)

我希望我的测试在找不到记录的情况下执行。但我不知道该怎么做。我尝试设置let(people) {nil}但它不起作用。有办法做到这一点吗?谢谢!

max*_*max 5

一开始这不是一个好的解决方案。在 Rails 中,您希望使用它rescue_from来处理控制器级别的常见错误。

class ApplicationController
  rescue_from ActiveRecord::RecordNotFound, with: :not_found

  def not_found
    respond_to do |format|
      format.json { head :404 }
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

这使您可以使用继承来干燥您的代码。

render json: { error: 'Failed') }
Run Code Online (Sandbox Code Playgroud)

是一种反模式。如果请求失败,您应该通过发送正确的 HTTP 状态代码告诉客户端。

如果你想测试你的控制器是否正确处理丢失的资源,你可以这样做:

let(:people) { create(:people) }
let(:people_id) { people.id }
let(:user) { people}

it "returns the correct response code if the person cannot be found" do
  get '/people/notarealid'
  expect(response).to have_http_status :not_found
end
Run Code Online (Sandbox Code Playgroud)

这不使用任何存根并实际测试实现。