0

假设我的 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)?

4

1 回答 1

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?")
于 2012-12-07T11:28:41.717 回答