【问题标题】:Decoupling service classes from the Rails environment从 Rails 环境中解耦服务类
【发布时间】:2012-12-07 10:50:51
【问题描述】:

假设我的 rails 应用程序中有一个服务类。它的作用并不重要,但让我们假设它可以用于向客户端推送通知。

# lib/services/event_pusher.rb
class EventPusher
  def initialize(client)
    @client = client
  end

  def publish(event)
    PusherGem.trigger(@client, event)
  end
end

我现在可以在我的控制器中使用这个类:

require "lib/services/event_pusher"

class WhateverController < ApplicationController
  def create
    @whatever = Whatever.new(params[:whatever])

    if @whatever.save
      EventPusher.new(current_user).publish('whatever:saved')
    end
  end
end

现在,当我调用publish 时,此服务类向第三方发出请求。我不希望在运行测试时发生这种情况。

在我看来,我有两个选择。

选项 1:
我必须记住通过环境检查对所有对EventPusher.trigger 的调用进行后缀。请记住,我可以在我的应用程序的每个创建/更新/销毁操作中调用它。

if @whatever.save
  EventPusher.new(current_user).publish('whatever:saved') unless Rails.env.test?
end

选项 2:
我必须将我的服务类与 Rails 耦合。

def publish(event)
  PusherGem.trigger(@client, event) unless Rails.env.test?
end

哪个是正确的选项(或者是否有秘密选项 3)?

【问题讨论】:

    标签: ruby-on-rails ruby decoupling


    【解决方案1】:

    你在使用 RSpec 吗?如果是这样,您可以在测试本身中覆盖 EventPusher 的发布方法的功能,如下所示:

    EventPusher.any_instance.stub(:publish)
    

    上面的代码用一个返回 nil 的空方法替换了原来的 publish 方法。该方法仍然存在并且仍然会被调用,但它不会在您的测试范围内做任何事情。

    如果其他代码期望发布方法返回一些东西,例如'true'表示成功,那么你可以添加以下内容:

    EventPusher.any_instance.stub(:publish).and_return(true)
    

    或者,如果您希望覆盖 PusherGem 的静态触发方法,则使用以下稍微不同的语法:

    PusherGem.stub!(:trigger)
    

    PusherGem.stub!(:trigger).and_return("something here, perhaps?")
    

    【讨论】:

      猜你喜欢
      • 2019-07-29
      • 2019-05-24
      • 2020-03-20
      • 1970-01-01
      • 2013-12-06
      • 2015-11-16
      • 2011-02-07
      • 2021-03-12
      • 2016-03-12
      相关资源
      最近更新 更多