使用RSpec双打时防止ArgumentError

时间:2016-08-26 11:46:57

标签: ruby rspec error-handling exception-handling mocking

我目前正在尝试使用以下代码引发错误:

class NasaController
  attr_reader :plateau, :current_rover

  def initialize(plateau:)
    @plateau = plateau
    @current_rover = []
  end

  def link_to_rover(robotic_rover)
    raise ArgumentError, "#{robotic_rover.class}" unless robotic_rover.is_a? RoboticRover
    @current_rover = robotic_rover
  end
end

它有效!大!但........

我的测试是:

describe NasaController do
  subject(:controller) { described_class.new(plateau: plateau) }

  let(:robotic_rover) do
    double(:robotic_rover, #some_methods...)
  end

  let(:plateau) { double(:plateau, rover_landed: landed_rover) }

  describe 'interacting with a rover' do
    context 'when a RoboticRover is used' do
      before { controller.link_to_rover(robotic_rover) }

      it 'can create a link' do
        expect(controller.current_rover).to eq robotic_rover
      end

    context 'when something other than a RoboticRover is used' do
      it 'raises an error at #link_to_rover' do
        expect { controller.link_to_rover(plateau) }.to raise_error 'Error!'
      end
    end
  end
end

这导致我的第二次测试通过,因为controller.link_to_rover(plateau)没有链接RoboticRover。

但是,我的第一次失败是因为controller.link_to_rover(robotic_rover)也不是RoboticRover,它是RoboticRover的两倍。有没有人有解决这个问题的任何指导?

1 个答案:

答案 0 :(得分:1)

您需要允许robotic_rover接收is_a?,参数为RoboticRover,并让它返回true。尝试将以下内容添加到失败的测试中:

allow(robotic_rover).to receive(:is_a?).with(RoboticRover).and_return(true)

或添加到double:

let(:robotic_rover) do
    double(:robotic_rover, is_a?: RoboticRover
end

有关详细信息,请参阅here