Ruby RSpec:如何模拟接受参数的对象和方法

Ruby RSpec:如何模拟接受参数的对象和方法,ruby,unit-testing,rspec,mocking,Ruby,Unit Testing,Rspec,Mocking,我正在为我为目录对象创建的CommandLineInterface类编写RSpec单元测试。CommandLineInterface类使用此目录对象打印出我的目录中的人员列表目录有一个#sort_by(param)方法,该方法返回字符串数组。字符串的顺序取决于传递给#sort_by方法的参数(例如,sort_by(“性别”)。在我的CLI规范中模拟此目录行为的正确方法是什么?我会使用双实例吗?我不知道对于采用参数(如按性别排序)的方法如何执行此操作 我只使用Ruby和RSpec。这里没有使用Ra

我正在为我为
目录
对象创建的
CommandLineInterface
类编写RSpec单元测试。
CommandLineInterface
类使用此
目录
对象打印出我的
目录
中的人员列表
目录
有一个
#sort_by(param)
方法,该方法返回字符串数组。字符串的顺序取决于传递给
#sort_by
方法的
参数(例如,
sort_by(“性别”)
。在我的CLI规范中模拟此
目录
行为的正确方法是什么?我会使用双实例吗?我不知道对于采用参数(如按性别排序)的方法如何执行此操作

我只使用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

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

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

  • 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

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