【问题标题】:RSpec `should_receive` behaviour with multiple method invocation具有多个方法调用的 RSpec `should_receive` 行为
【发布时间】:2013-06-22 09:10:35
【问题描述】:

考虑以下测试:

class A
  def print(args)
    puts args
  end
end

describe A do
  let(:a) {A.new}

  it "receives print" do
   a.should_receive(:print).with("World").and_call_original

   a.print("Hello")
   a.print("World")
 end
end

RSpec Documentation 说:

使用 should_receive() 设置接收者应该收到的期望 示例完成前的消息。

所以我期待这个测试通过,但事实并非如此。它失败并显示以下消息:

Failures:

1) A receives print
 Failure/Error: a.print("Hello")
   #<A:0x007feb46283190> received :print with unexpected arguments
     expected: ("World")
          got: ("Hello")

这是预期的行为吗?有没有办法让这个测试通过?

我正在使用 ruby 1.9.3p374rspec 2.13.1

【问题讨论】:

  • 您遵循什么文档?你会分享链接吗?这是我要求自学... :))
  • 问题中有链接。 :)

标签: ruby testing rspec rspec2


【解决方案1】:

添加allow(a).to receive(:print)怎么样?

require 'rspec'

class A
  def print(args)
    puts args
  end
end

describe A do
  let(:a) { described_class.new }

  it 'receives print' do
    allow(a).to receive(:print)
    expect(a).to receive(:print).with('World')

    a.print('Hello')
    a.print('World')
  end
end

基本上,allow(a).to_receive(:print) 允许“a”接收带有任何参数的“打印”消息。因此a.print('Hello') 不会通过测试。

【讨论】:

    【解决方案2】:

    should_receive 不仅检查预期的方法是否被调用,而且意外的方法是否没有被调用。只需为您期望的每个调用添加一个规范:

    class A
      def print(args)
        puts args
      end
    end
    
    describe A do
      let(:a) {A.new}
    
      it "receives print" do
       a.should_receive(:print).with("World").and_call_original
       a.should_receive(:print).with("Hello").and_call_original
    
       a.print("Hello")
       a.print("World")
     end
    end
    

    【讨论】:

    • 问题是这是一个单元测试,我不想用与我希望测试的功能无关的调用来污染它。
    【解决方案3】:

    这个怎么样?

    class A
      def print(args)
        puts args
      end
    end
    
    describe A do
      let(:a) {A.new}
    
      it "receives print" do
       a.should_receive(:print).with("World").and_call_original
       # it's important that this is after the real expectation
       a.should_receive(:print).any_number_of_times
    
       a.print("Hello")
       a.print("World")
     end
    end
    

    它增加了您可能想要避免的第二个期望。但是,考虑到@vrinek 的问题,该解决方案的优点是提供了正确的失败消息(预期:1 次,收到:0 次)。干杯!

    【讨论】:

      【解决方案4】:

      这应该可行:

      class A
        def print(args)
          puts args
        end
      end
      
      describe A do
        let(:a) {A.new}
      
        it "receives print" do
         a.stub(:print).with(anything())
         a.should_receive(:print).with("World").and_call_original
      
         a.print("Hello")
         a.print("World")
       end
      end
      

      测试失败是因为您设置了一个精确的期望“a 应该接收 :print with 'World'”,但是 rspec 注意到 a 对象正在接收带有 'Hello' 的 print 方法,因此它没有通过测试。在我的解决方案中,我允许使用任何参数调用 print 方法,但它仍会以“World”作为参数来跟踪调用。

      【讨论】:

      • 本例中,如果省略a.print("World")这一行,会失败吗?
      • @vrinek 是的,Failure/Error: a.should_receive(:print).with("World").and_call_original #&lt;A:0x007feec13ae2a8&gt; received :print with unexpected arguments 是这样的
      • 我觉得a.stub(:print).with(anything).and_call_original会更好
      • 哦,当然,这取决于该方法调用是查询还是命令:)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-22
      • 2014-12-16
      • 2014-02-11
      • 2012-06-06
      • 2010-11-22
      • 1970-01-01
      相关资源
      最近更新 更多