我有一个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只是绕过了救援块而没有运行它。是什么原因造成的?我not在任何地方都使用bypass_rescue
RSpec方法,这也是一个新项目。
使用中:
Rails 4.2.6
Rake 10.5.0
RSpec-core 3.3.2
RSpec-rails 3.3.3
实际上,问题与控制器中的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