1

假设我有这样的代码:

class Car
  def test_drive!; end
end

class AssemblyLine
  def produce!
    car = Car.new
    car.test_drive!
  end
end

现在,使用 RSpec 我想在AssemblyLine不锻炼Car的情况下进行测试/规范。我听说我们不在 Ruby 中进行依赖注入,而是使用 stub new

describe AssemblyLine
  before do
    Car.stub(:new).and_return(double('Car'))
  end

  describe '#produce'
    it 'test-drives new cars' do
      the_new_instance_of_car.should_receive(:test_drive) # ???
      AssemblyLine.new.produce!
    end
  end
end

如您所见,问题在于the_new_instance_of_car. produce它在被调用之前还不存在,并且在produce返回之后设置任何方法调用期望为时已晚。

我可以想到一种解决方法,涉及在存根new方法中的回调,但这相当可怕。必须有更优雅和惯用的方法来解决这个看似常见的问题。对...?


更新:这是我解决它的方法。

describe AssemblyLine
  def stub_new_car(&block)
    Car.stub(:new) do
      car = double('Car')
      block.call(car) if block
      car
    end
  end

  before { stub_new_car } # to make other tests use the stub as well

  describe '#produce'
    it 'test-drives new cars' do
      stub_new_car { |car| car.should_receive(:test_drive) }
      AssemblyLine.new.produce!
    end
  end
end
4

1 回答 1

1

您可以对测试替身设定期望:

describe AssemblyLine do
  let(:car) { double('Car') }
  before { Car.stub(:new) { car } }

  describe "#produce" do
    it "test-drives new cars" do
      car.should_receive(:test_drive!)
      AssemblyLine.new.produce!
    end
  end
end

您还可以调用any_instance该类(我认为从 RSpec 2.7 开始):

describe AssemblyLine do
  describe "#produce" do
    it "test-drives new cars" do
      Car.any_instance.should_receive(:test_drive!)
      AssemblyLine.new.produce!
    end
  end
end
于 2012-06-17T08:20:32.233 回答