RSpec:如何模拟带参数的对象和方法

时间:2015-08-14 15:04:32

标签: ruby unit-testing rspec mocking

我正在为我CommandLineInterface对象创建的Directory类编写RSpec单元测试。 CommandLineInterface类使用此Directory对象打印出Directory中的人员列表。 Directory有一个#sort_by(param)方法,返回一个字符串数组。字符串的顺序取决于传递给param方法的#sort_by(例如,sort_by("gender")。在CLI中模拟这种Directory行为的正确方法是什么specs?我会使用instance_double吗?我不知道如何为一个带参数的方法做这个,比如按性别排序。

我只使用Ruby和RSpec。这里没有使用Rails,ActiveRecord等。

我要模拟的类和方法的片段:

class Directory
  def initialize(params)
    #
  end

  def sort_by(param)
    case param
    when "gender" then @people.sort_by(&:gender)
    when "name" then @people.sort_by(&:name)
    else raise ArgumentError
    end
  end
end

1 个答案:

答案 0 :(得分:2)

这完全取决于您的对象如何协作。

您的问题中缺少一些信息:

  • CommandLineInterface如何使用Directory?它是单独创建一个实例还是作为参数接收一个实例?
  • 您是在测试类方法还是实例方法? (首选实例方法)

如果传入依赖对象,可以执行以下操作:

require 'rspec/autorun'

class A
  def initialize(b)
    @b = b
  end

  def foo(thing)
    @b.bar(thing)
  end
end

RSpec.describe A do
  describe '#foo' do
    context 'when given qux' do
      let(:b) { double('an instance of B') }
      let(:a) { A.new(b) }
      it 'calls b.bar with qux' do
        expect(b).to receive(:bar).with('qux')
        a.foo('qux')
      end
    end
  end
end

如果类初始化了依赖对象,并且知道哪个实例得到了消息并不重要,那么你可以这样做:

require 'rspec/autorun'

B = Class.new

class A
  def initialize
    @b = B.new
  end

  def foo(thing)
    @b.bar(thing)
  end
end

RSpec.describe A do
  describe '#foo' do
    context 'when given qux' do
      let(:a) { A.new }
      it 'calls b.bar with qux' do
        expect_any_instance_of(B).to receive(:bar).with('qux')
        a.foo('qux')
      end
    end
  end
end

如果您只想隐藏返回值而不测试是否收到了确切的消息,则可以使用allow

require 'rspec/autorun'

B = Class.new

class A
  def initialize
    @b = B.new
  end

  def foo(thing)
    thing + @b.bar(thing)
  end
end

RSpec.describe A do
  describe '#foo' do
    context 'when given qux' do
      let(:a) { A.new }
      it 'returns qux and b.bar' do
        allow_any_instance_of(B).to receive(:bar).with('qux') { 'jabber' }
        expect(a.foo('qux')).to eq('quxjabber')
      end
    end
  end
end