【问题标题】:RSpec: How to mock an object and methods that take parametersRSpec:如何模拟带参数的对象和方法
【发布时间】:2015-08-14 15:04:32
【问题描述】:

我正在为我为 Directory 对象创建的 CommandLineInterface 类编写 RSpec 单元测试。 CommandLineInterface 类使用这个Directory 对象来打印出我的Directory 中的人员列表。 Directory 有一个 #sort_by(param) 方法,它返回一个字符串数组。字符串的顺序取决于传递给#sort_by 方法的param(例如sort_by("gender")。在我的CLI 规范中模拟Directory 行为的正确方法是什么?我会使用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

【问题讨论】:

  • 粘贴实际代码会更容易回答。

标签: ruby unit-testing rspec mocking


【解决方案1】:

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

您的问题缺少一些信息:

  • 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-19
    • 1970-01-01
    相关资源
    最近更新 更多