在rails单元测试中测试ExceptionNotification中间件

时间:2016-01-18 19:35:29

标签: ruby-on-rails ruby rspec rack middleware

我有一个我正在测试的服务类。服务类对外部资源进行API调用。如果资源变回空,我想提出一个使用ExceptionNotification gem发送电子邮件的异常。

此gem作为中间件运行,通常在测试环境中不启用。但是,在我的服务类测试中,我想测试异常通知是否已经消失,因为我们被告知API请求失败是非常重要的。

我对中间件的理解是它们通常位于请求和应用程序的上下文中。但是,如果我在ExceptionNotification中启用config/environments/test.rb gem并运行我的单元测试,则会发送异常通知电子邮件。

所以,我的问题是如何在没有“app”添加的情况下暂时打开和关闭此中间件进行此测试,因此我认为这必须是可能的,而不是在功能规范中。

好的,这是我正在使用并启动的代码:

class MyService
  ThingNotFound = Class.new(Exception)

  def self.doit(params)
    the_thing = ApiResource.get_the_thing(params)
    raise ThingNotFound unless the_thing.present?
    return the_thing
  rescue ThingNotFound => e
    ExceptionNotifier.notify_exception(e, data: {params: params}) 
  end
end

config/environments/test.rb中,这是ExceptionNotifier中间件代码:

config.before_initialize do 
  MyApp::Application.config.middleware.use ExceptionNotification::Rack
end

1 个答案:

答案 0 :(得分:0)

这是我提出的一种黑客方式。对替代品开放。基本上,当你将它包含在test.rb中时,它会实例化设置一些类变量的中间件,这样你就可以在Rack应用程序的上下文之外使用它,所以我们只需要重现它。

 describe 'MyService' do

   before { ExceptionNotification::Rack.new(Recognize::Application, email: {:email_prefix => "[PREFIX] ", :sender_address => "whatever@whatever.com", :exception_recipients => %w(noone@noone.com)}) }
   after { ExceptionNotifier.class_variable_set("@@notifiers", {}) }

    it 'sends an exception email when no thing is found' do
      ApiResource.stub(get_the_thing: nil)
      expect{ MyService.doit({}) }.to change{ActionMailer::Base.deliveries.length}.by(1)
    end
 end