RSpec忽略了我在控制器

时间:2016-03-17 21:21:44

标签: ruby-on-rails ruby-on-rails-4 rspec

我有一个Rails控制器,它对数据库进行健康检查,如下所示:

def health_check
  begin
    status = ActiveRecord::Base.connected? ? 'UP' : 'DOWN'
  rescue
    status = 'DOWN'
  end
  render text: status
end

我正在尝试为此创建一个RSpec控制器规范,正负响应的规范有效,但当我尝试测试救援块时,RSpec似乎忽略了它:

RSpec.describe(HealthCheckController) do
  context 'When the check raises an exception' do
    before :each do
      allow(ActiveRecord::Base).to receive(:connected?).and_raise(OCIException) # Using Oracle
    end

    it 'should render text DOWN' do
      # First attempt
      get :health_check
      expect(response.body).to eq 'DOWN'

      # Second attempt
      expect { get :health_check }.to raise_error
      expect(response.body).to eq 'DOWN'
    end
  end
end

我尝试使用上面it块内的两个代码(分开)。

对于第一个,RSpec失败了:

 Failure/Error: get :health_check
     OCIException:
       OCIException

对于第二个,它也失败了,而这个更“熟悉”的消息代替了:

Failure/Error: expect(response.body).to eq 'DOWN'

       expected: "DOWN"
            got: ""

       (compared using ==)

我还检查了响应返回的HTTP代码,它是200,所以响应本身没问题,没有500错误。

就好像RSpec只是绕过救援区而没有运行它。可能是什么导致了这个?我在任何地方使用bypass_rescue RSpec方法,这也是一个新项目。

使用:

Rails 4.2.6
Rake 10.5.0
RSpec-core 3.3.2
RSpec-rails 3.3.3

1 个答案:

答案 0 :(得分:0)

实际上,问题与控制器中的rescue块无关。相反,这是由于您通过在ActiveRecord::Base#connected?块中存根而覆盖了before造成的。

在控制器中调用render将启动与数据库的连接。 ActiveRecord::Base#connected?在过程中某个地方被调用(实际上是两次),但是它没有返回应该返回的内容,而是引发了您在设置中定义的异常。

在第一个示例中,异常在您的期望之前引发,因此在失败消息中具有明确的异常名称。

在第二个示例中,您的raise_error期望抑制了该异常,因此RSpec可以继续进行下一个。由于控制器中的render调用永远不会运行(由于错误)而导致失败的地方,结果是响应正文永远不会有机会被填充。

要确认在致电ActiveRecord::Base#connected?时确实会呼叫render,请尝试运行以下规范。您会看到它是绿色的,这意味着该方法在该过程中已被调用两次。您也可以尝试将render替换为head :ok,在这种情况下,ActiveRecord::Base#connected?只会被调用一次。

RSpec.describe ApplicationController do
  controller do
    def index
      render json: ''
    end
  end

  specify 'test' do
    expect(ActiveRecord::Base).to receive(:connected?).twice
    get :index
  end
end