【问题标题】:RSpec -- test if block called with block defined in beforeRSpec -- 测试是否使用之前定义的块调用块
【发布时间】:2012-11-07 23:18:37
【问题描述】:

recently asked 如何在 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,nodes 由它们的参数和代码块定义(可以在节点范围内定义其他东西)。由于节点块定义的东西可能非常通用,至少在第一次尝试时,我只需要确保对块进行评估,并且将考虑用户提供的内容。现在不管它是什么。

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

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

【问题讨论】:

  • letlet! 是比 before 更好的方法来初始化用于规范的值。见relishapp.com/rspec/rspec-core/v/2-11/docs/helper-methods/…。我很确定你需要一个有期望的double(模拟)。然后在其他规范中用实际代码替换 let 这是双精度代码。
  • 嗯...这一切如何适合我的问题?
  • 我很想知道更多关于这里更大背景的信息。这似乎是在测试实现,而不是行为,这通常是您想要避免的。
  • 感谢您的宝贵意见!我对我的问题进行了一些解释。

标签: ruby testing rspec call block


【解决方案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,这可能意味着你有玩一下)使用letdouble 来检查它是否被调用,并避免使用before,这确实是为了副作用不是设置变量以用于规格。

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

【讨论】:

  • 感谢您的回答。效果很好。我只需要将let(:node_block) 中的double 调用封装到Proc 中,因为这是Node.new 所要求的。还要感谢您向我指出有关测试实施和行为的疑问。当我重构我的代码时,我现在可能应该重构我的测试;-) 我可能会很棘手,并且值得在这里提出另一个问题,但我会稍后再做。上面@zetetic评论的澄清将在一段时间内出现;-)
猜你喜欢
  • 2012-10-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多