Ruby 如何使用rspec测试dslapi方法

Ruby 如何使用rspec测试dslapi方法,ruby,rspec,Ruby,Rspec,我想测试一个方法是否接收一个块。。。但是我的rspec存根返回(无参数) 这里有一个人为的例子 class Foo def self.bar &block end end describe Foo do before do Foo.stub(:bar) Foo.bar { 'foo'} end it 'should' do expect(Foo).to have_received(:bar).with(kind_of(Proc)) end

我想测试一个方法是否接收一个块。。。但是我的rspec存根返回
(无参数)

这里有一个人为的例子

class Foo
  def self.bar &block
  end
end

describe Foo do
  before do
    Foo.stub(:bar)
    Foo.bar { 'foo'}
  end
  it 'should' do
    expect(Foo).to have_received(:bar).with(kind_of(Proc))
  end
end
结果

  1) Foo should
     Failure/Error: expect(Foo).to have_received(:bar).with(kind_of(Proc))
       <Foo (class)> received :bar with unexpected arguments
         expected: (#<RSpec::Mocks::ArgumentMatchers::KindOf:0x1022a7b20 @klass=Proc>)
              got: (no args)
bar.rb


我不认为有任何方法可以验证在事实发生后是否通过了块,但如果使用正常的预执行预期,可以按如下方式检查它:

class Foo
  def self.bar &block
    puts 'DO NOT RUN'
  end
end

describe 'Foo#bar' do
  it 'should confirm a block is passed' do
    expect(Foo).to receive(:bar) {|&block| expect(block).to be_a(Proc)}
    Foo.bar {}
  end
  it 'should confirm a block is not passed' do
    expect(Foo).to receive(:bar) {|&block| expect(block).to be_nil}
    Foo.bar
  end
end
如果您不介意实际屈服于块,那么可以使用
。和_yield
,如果块不存在,这将生成预期错误

class Foo
  def self.bar &block
  end
end

describe Foo do
  before do
    Foo.stub(:bar), y
  end
  it 'should' do
    expect(Foo).to receive(:bar).and_yield
    Foo.bar {}
  end
end

为了测试一个块是否被调用,而不必运行它,并查看收益率是否失败,我决定重新打开这个类并利用一个类变量。这是一个临时的解决方法,因为(IMO)rspec应该负责这个功能

class Foo
  def self.bar &block
    puts 'DO NOT RUN'
  end
end

describe Foo do
  before do
    class Foo
      def self.bar &block
        Foo.send(:class_variable_set, :@@bar_val, block)
      end
      Foo.bar {} # this line is dynamic in my real specs :)
    end
  end

  after :all do
    load 'foo' # to revert back to the original class
  end

  it 'should' do
    expect(Foo.send(:class_variable_get, :@@bar_val)).to be_a Proc
  end
end

真的。。。这是因为它是一个人为的例子。。。。试想一下这个测试并不是毫无意义的:)对不起,我把这个问题误读为使用了
应该接收
而不是
应该接收
。我将更新我的答案。
。并且_yield
有效,但我想阻止运行该过程。我决定使用stubing
Foo.stub
将该块分配给一个类变量,我可以检查该类变量是否为proc的实例。@brewster您是否介意发布您最终完成的操作?我不明白,我想知道。我正在考虑为RSpec生成一个PR,以引入一个
with_block
方法,该方法将在不调用块的情况下检查块的存在,我想了解任何替代方法。刚刚看到您的答复。。。我刚刚添加了我的变通解决方案作为另一个答案。向rspec提交PR完全合适。如果需要的话,我可以想出一个非人为的例子来说明这实际上是如何有用的。谢谢。另一种方法见我的更新答案。
class Foo
  def self.bar &block
    puts 'DO NOT RUN'
  end
end

describe 'Foo#bar' do
  it 'should confirm a block is passed' do
    expect(Foo).to receive(:bar) {|&block| expect(block).to be_a(Proc)}
    Foo.bar {}
  end
  it 'should confirm a block is not passed' do
    expect(Foo).to receive(:bar) {|&block| expect(block).to be_nil}
    Foo.bar
  end
end
class Foo
  def self.bar &block
  end
end

describe Foo do
  before do
    Foo.stub(:bar), y
  end
  it 'should' do
    expect(Foo).to receive(:bar).and_yield
    Foo.bar {}
  end
end
class Foo
  def self.bar &block
    puts 'DO NOT RUN'
  end
end

describe Foo do
  before do
    class Foo
      def self.bar &block
        Foo.send(:class_variable_set, :@@bar_val, block)
      end
      Foo.bar {} # this line is dynamic in my real specs :)
    end
  end

  after :all do
    load 'foo' # to revert back to the original class
  end

  it 'should' do
    expect(Foo.send(:class_variable_get, :@@bar_val)).to be_a Proc
  end
end