如何测试服务对象

时间:2014-03-28 18:53:05

标签: ruby-on-rails ruby-on-rails-4 rspec

我在下面编写了服务对象。

class LeadGeneration
  def initialize contact_id
    @lead = Lead.find_or_initialize_by(contact_id: contact_id)
  end

  def lead
    @lead
  end

  def activate_lead
    lead.active!
  end

  def stale_lead
     lead.stale!
  end
end

我对如何测试它有点困惑。我写了下面的规范

require 'spec_helper'

describe LeadGeneration do
    let(:contact) { FactoryGirl.create(:contact) }

 it "#activate_lead" do
    lg = LeadGeneration.new(contact.id)
    expect(lg.lead).to receive(:active!)
    lg.activate_lead
  end

  it "#stale_lead" do
    lg = LeadGeneration.new(contact.id)
    expect(lg.lead).to receive(:stale!)
    lg.stale_lead
  end
end

此规范工作正常,但我想在不暴露生成的潜在客户的情况下执行此操作。我究竟该如何解决这个问题。我可以用

expect(Lead.any_instance).to receive(:active!)

但从我的阅读来看,这是不好的做法。有什么想法吗?

1 个答案:

答案 0 :(得分:2)

因为在这个例子中你所测试的是主导对象接收消息,你可以通过存储#lead来返回一个你设定期望值的模拟对象:

it "#activate_lead" do
  lead = double('lead')
  lg = LeadGeneration.new(contact.id)
  # make #lead return our test double whenever it's called
  allow(lg).to receive(:lead) { lead }
  # our test double should receive the message
  expect(lead).to receive(:active!)
  lg.activate_lead
end

这意味着您可以将#lead方法移动到私有/受保护的空间,因为您不必再​​直接调用它。