在某些RSpec rails请求示例中测试HTTP状态代码,但是对于其他RSPro rails请求示例

das*_*s-g 19 ruby rspec ruby-on-rails rspec-rails actiondispatch

在测试的Rails 4.2.0应用程序中rspec-rails,我提供了一个JSON Web API,它具有类似REST的资源,具有强制属性mand_attr.

我想测试一下,BAD REQUEST当POST请求中缺少该属性时,此API会回答HTTP代码400().(请参阅第二个示例.)我的控制器尝试通过抛出一个来生成此HTTP代码ActionController::ParameterMissing,如下面的第一个RSpec示例所示.

其他 RSpec示例中,我希望通过示例(如果它们是预期的)挽救引发的异常或者命中测试运行器,因此它们会显示给开发人员(如果错误是意外的),因此我不想要去除

  # Raise exceptions instead of rendering exception templates.
  config.action_dispatch.show_exceptions = false
Run Code Online (Sandbox Code Playgroud)

来自config/environments/test.rb.

我的计划是在请求规范中包含以下内容:

describe 'POST' do
  let(:perform_request) { post '/my/api/my_ressource', request_body, request_header }
  let(:request_header) { { 'CONTENT_TYPE' => 'application/json' } }

  context 'without mandatory attribute' do
    let(:request_body) do
      {}.to_json
    end

    it 'raises a ParameterMissing error' do
      expect { perform_request }.to raise_error ActionController::ParameterMissing,
                                                'param is missing or the value is empty: mand_attr'
    end

    context 'in production' do
      ###############################################################
      # How do I make this work without breaking the example above? #
      ###############################################################
      it 'reports BAD REQUEST (HTTP status 400)' do
        perform_request
        expect(response).to be_a_bad_request
        # Above matcher provided by api-matchers. Expectation equivalent to
        #     expect(response.status).to eq 400
      end
    end
  end

  # Below are the examples for the happy path.
  # They're not relevant to this question, but I thought
  # I'd let you see them for context and illustration.
  context 'with mandatory attribute' do
    let(:request_body) do
      { mand_attr: 'something' }.to_json
    end

    it 'creates a ressource entry' do
      expect { perform_request }.to change(MyRessource, :count).by 1
    end

    it 'reports that a ressource entry was created (HTTP status 201)' do
      perform_request
      expect(response).to create_resource
      # Above matcher provided by api-matchers. Expectation equivalent to
      #     expect(response.status).to eq 201
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

我找到了两个工作和一个部分工作的解决方案,我将作为答案发布.但我对他们中的任何一个都不是特别满意,所以如果你能想出更好的东西(或者只是不同的东西),我希望看到你的方法!另外,如果请求规范是错误的规范类型来测试它,我想知道.

我预见到了这个问题

为什么要测试Rails框架而不仅仅是Rails应用程序?Rails框架有自己的测试!

所以让我先发制人地回答:我觉得我不是在这里测试框架,而是我是否正确使用框架.我的控制器不继承,ActionController::BaseActionController::API我不知道是否默认ActionController::API使用ActionDispatch::ExceptionWrapper,或者我是否必须告诉我的控制器以某种方式这样做.

awe*_*ndt 5

您想为此使用RSpec筛选器。如果以这种方式进行,则对的修改Rails.application.config.action_dispatch.show_exceptions将是示例的本地操作,并且不会干扰您的其他测试:

# This configure block can be moved into a spec helper
RSpec.configure do |config|
  config.before(:example, exceptions: :catch) do
    allow(Rails.application.config.action_dispatch).to receive(:show_exceptions) { true }
  end
end

RSpec.describe 'POST' do
  let(:perform_request) { post '/my/api/my_ressource', request_body }

  context 'without mandatory attribute' do
    let(:request_body) do
      {}.to_json
    end

    it 'raises a ParameterMissing error' do
      expect { perform_request }.to raise_error ActionController::ParameterMissing
    end

    context 'in production', exceptions: :catch do
      it 'reports BAD REQUEST (HTTP status 400)' do
        perform_request
        expect(response).to be_a_bad_request
      end
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

exceptions: :catch是RSpec的发言“任意元数据”,我这里选择的命名是为了便于阅读。


das*_*s-g 0

nil从部分模拟的应用程序配置返回

    context 'in production' do
      before do
        allow(Rails.application.config.action_dispatch).to receive(:show_exceptions)
      end

      it 'reports BAD REQUEST (HTTP status 400)' do
        perform_request
        expect(response).to be_a_bad_request
      end
    end
Run Code Online (Sandbox Code Playgroud)

或者更明确地使用

    context 'in production' do
      before do
        allow(Rails.application.config.action_dispatch).to receive(:show_exceptions).and_return nil
      end

      it 'reports BAD REQUEST (HTTP status 400)' do
        perform_request
        expect(response).to be_a_bad_request
      end
    end
Run Code Online (Sandbox Code Playgroud)

如果这是唯一正在运行的示例,则可以工作。但如果是的话,我们也可以从 中删除该设置config/environments/test.rb,所以这有点没有实际意义。当有多个示例时,这将不起作用,因为Rails.application.env_config()查询此设置并缓存其结果。