假设我的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)?
答案 0 :(得分: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?")