拨打第三方服务的电话是可测试的

时间:2013-09-11 04:52:58

标签: ruby

我想知道这是否是在我的测试中避免调用第三方服务的好策略。

我有2个类封装了对第三方服务的调用,我称之为PersonIdentifier和FIleManager。

为了使这些类可测试,我将它们传递给另一个类的构造函数,如下所示:

CreateContact.new(current_user, input, PersonIdentifier.new, FileManager.new)

但是,此CreateContact实例的创建可能在类方法或实例方法中。因此,在类方法的情况下,我创建另一个创建实例的类方法,例如

  def self.create_contact(current_user, input)
    CreateContact.new(current_user, input, PersonIdentifier.new, FileManager.new)
  end

然后在我的测试中,我使用instance_eval来覆盖这个方法,例如

  def setup
    super

    EmailIdentifier.instance_eval do
      def create_contact(current_user, input)
        CreateContact.new(current_user, input, TestPersonIdentifier.new, TestFileManager.new)
      end
    end
  end

在我的测试设置中添加多个class_eval或instance_eval会有点痛苦。

有更好的方法吗?

1 个答案:

答案 0 :(得分:0)

首先,在您的代码中,依赖性太强了。

def self.create_contact(current_user, input)
  CreateContact.new(current_user, input, PersonIdentifier.new, FileManager.new)
end

您在代码中隐式调用了两个外部对象。

我将首先重构代码以允许依赖注入

def self.create_contact(user, input, person_identifier=nil, file_manager=nil)
  # current_user seems very specific, replaced by a general name 'user'
  person_identifier ||= PersonIdentifier.new
  file_manager      ||= FilerManager.new
  new(user, input, person_identifier, file_manager)
end

通过这种方式,任何实例都可以注入到这个方法中,你已经从这两个类中删除了依赖。

然后,在测试中,您需要的是简单地模拟这两个实例。我只熟悉Rspec所以不能提供具体的代码,但原理是一样的。