1

最近询问如何在 RSpec 中测试是否调用了一个块,并且该问题的答案似乎在一个简单的情况下有效。问题是当块的初始化更复杂时。然后它before在上下文中被许多不同的测试完成并重用,其中一个测试块是否被评估。请参阅示例:

context "the node definition using block of code" do
  before do
     @n=node do
        # this block should be called
     end
     # some more complex setup concerning @n
  end

  it "should call the block" do
     # how to test it?
  end

  # here a bunch of other tests using @n

end

在这种情况下,具有副作用改变局部变量值的解决方案不起作用。从块中引发异常是没有用的,因为必须正确评估整个语句才能被其他测试使用。

显然我可以单独进行测试,但它似乎很臭,因为我必须复制粘贴初始化部分,并且因为被称为块的测试本身就属于这个上下文。

在这种情况下如何测试块是否被评估?


以下@zetetic 提出的问题的解释。

上下文是我正在实现一种 DSL,节点由其参数和代码块定义(可以在节点范围内定义其他内容)。由于节点块定义的东西可能非常通用,至少在第一次尝试时,我只需要确保对块进行评估,并且将考虑用户提供的内容。现在不管它是什么。

可能我现在应该重构我的测试并使用模拟使它们测试行为而不是实现。然而,它会有点棘手,因为一些混合和动态处理发送到对象的消息。目前,此类测试的概念在我的脑海中有点模糊;-)

无论如何,您的回答和评论帮助我更好地理解 RSpec 是如何工作的,并解释了为什么我正在尝试做的事情看起来好像不适合 RSpec。

4

1 回答 1

1

尝试这样的事情(未经我测试):

context "the node definition using block of code" do
  let(:node){
    node = Node.new "arg1", "arg2", node_block
    # more complex stuff here
    node
  }
  context "checking the block is called" do
    let(:node_block) {
      double = double("node_block")
      double.should_receive("some kind of arg").and_return("something")
      # this will now cause a fail if it isn't called
      double
    }
    it "should call the block" do
      node.blah()
    end
  end

  let(:node_block) {
    # some real code
  }

  subject { node.blah() }
  it { should == 2 }
  # ...
end

所以这是一段非常不稳定的代码(你必须填补空白,因为你没有付出太多,而且let显然也是一个 lambda,这可能意味着你必须玩弄它bit) 使用letand adouble来检查它是否被调用,并避免使用before,这实际上是为了副作用而不是设置用于规范的变量。

@zetetic 发表了一个非常有见地的评论,即您没有在这里测试行为。我不反对使用 rspec 来做更多的单元测试风格的东西(准则被打破),但你可能会问,如果没有调用一个真正的代码块,以后的测试将如何通过?在某种程度上,我什至不确定您是否需要检查块是否被调用,但只有您知道。

于 2012-11-08T09:13:19.993 回答