RSpec:存根自定义异常时出现TypeError

时间:2019-01-14 22:21:48

标签: ruby unit-testing rspec

我想测试Custom::Runner.run是否营救了所有StandardErrors并发出异常警报。

我在弄清楚如何对自定义错误类Custom::Error的调用进行存根时遇到了一些麻烦,并期望收到Custom::Alert.error并以double作为参数。

下面是一个完整的测试案例来演示该问题:

module Custom
  class Error < StandardError
  end
end

module Custom
  class Alert
    def self.error(exception, context = {})
    end
  end
end

module Custom
  class Runner
    def self.run
      request
    rescue => e
      Custom::Alert.error(e, { foo: :bar })
    end

    class << self
      def request
        raise Custom::Error.new('test')
      end
    end
  end
end

这是测试:

RSpec.describe Custom::Runner do
  describe '.run' do
    let(:custom_error_double) { instance_double(Custom::Error) }

    before do
      # could this be the culprit?
      allow(Custom::Error).to receive(:new)
        .with('test')
        .and_return(custom_error_double, 'test')
    end

    it 'fires a custom alert' do
      expect(Custom::Alert).to receive(:error)
        .with(custom_error_double, foo: :bar)

      described_class.run
    end
  end
end

测试失败:

Failures:                                                                                                                                                    
                                                                                                                                                                1) Custom::Runner.run fires a custom alert
     Failure/Error: Custom::Alert.error(e, { foo: :bar })                                                                                                    

       #<Custom::Alert (class)> received :error with unexpected arguments                                                                                    
         expected: (#<InstanceDouble(Custom::Error) (anonymous)>, {:foo=>:bar})                                                                              
              got: (#<TypeError: exception class/object expected>, {:foo=>:bar})
       Diff:             
       @@ -1,2 +1,2 @@
       -[#<InstanceDouble(Custom::Error) (anonymous)>, {:foo=>:bar}]
       +[#<TypeError: exception class/object expected>, {:foo=>:bar}]

我相信这是因为rescue需要一个例外,并且我要返回一个double。我已经尝试过提高.and_raise(custom_error_double),但是我仍然得到相同的TypeError: exception class/object expected

这里一定有我想念的东西。任何建议将不胜感激。

2 个答案:

答案 0 :(得分:1)

我猜想Custom::Error的实例双精度对象是InstanceDouble对象,而不是Exception对象,因此当您提高双精度值时会导致TypeError

您可以替换双线

 let(:custom_error_double) { instance_double(Custom::Error) }

带有真实的Custom::Error对象

 let(:custom_error) { Custom::Error.new }

避免这种情况。

答案 1 :(得分:0)

我相信您是完全正确的,例外与双重是问题所在。该错误具体是received :error with unexpected arguments,并且比较是双精度数与TypeError不匹配。在这种情况下,盲人rescue => e然后调用Custom::Alert.error(e, {foo: :bar})(以TypeError作为参数e),但是在测试中,.with()期望

这将起作用:

RSpec.describe Custom::Runner do
  describe '.run' do
    let(:custom_error) { Custom::Error.new }

    before do
      allow(Custom::Error).to receive(:new).with('test').and_return(custom_error, 'test')
    end

    it 'fires a custom alert' do
      expect(Custom::Alert).to receive(:error).with(custom_error, foo: :bar)

      described_class.run
    end
  end
end