Ruby RSpec—测试是否使用之前定义的块调用了块

Ruby RSpec—测试是否使用之前定义的块调用了块,ruby,testing,rspec,call,block,Ruby,Testing,Rspec,Call,Block,我知道如何在RSpec中测试是否调用了一个块,并且该问题的答案似乎在一个简单的情况下有效。问题是当块的初始化更复杂时。然后在之前的中完成,并在上下文中被许多不同的测试重用,其中一个测试是是否对块进行了评估。请参见示例: context“使用代码块的节点定义”do 在做之前 @n=节点do #应该调用此块 结束 #关于@n的一些更复杂的设置 结束 它“应该调用块”吗 #如何测试它? 结束 #这里有一系列使用@n的其他测试 结束 在这种情况下,具有改变局部变量值的副作用的解决方案不起作用。从块中引

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

context“使用代码块的节点定义”do
在做之前
@n=节点do
#应该调用此块
结束
#关于@n的一些更复杂的设置
结束
它“应该调用块”吗
#如何测试它?
结束
#这里有一系列使用@n的其他测试
结束
在这种情况下,具有改变局部变量值的副作用的解决方案不起作用。从块中引发异常是没有用的,因为整个语句必须经过正确的评估才能被其他测试使用

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

如何测试在这种情况下是否对块进行了评估


下面对@zettec提出的问题进行解释

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

也许我现在应该重构我的测试,使用mock让它们测试行为,而不是实现。但是,为了一些混合和动态处理发送到对象的消息,这将有点棘手。目前,这种测试的概念在我的头脑中有点模糊;-)

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

尝试类似的方法(未经我测试):

因此,这是一段非常不稳定的代码(你必须填补空白,因为你没有太多时间继续,而且
let
显然也是一个lambda,这可能意味着你必须对它进行一些处理),它使用
let
double
来检查它的调用,并避免在
之前使用
,这是真正的副作用,没有设置变量用于规格

@Zettetic做了一个很有见地的评论,说你不是在测试行为。我并不反对使用rspec来做更多的单元测试风格的事情(准则被打破),但是您可能会问,如果没有调用一个真正的代码块,那么当使用该代码块时,以后的测试将如何通过?在某种程度上,我甚至不确定您是否需要检查块是否被调用,但只有您知道。

尝试类似的方法(未经我测试):

因此,这是一段非常不稳定的代码(你必须填补空白,因为你没有太多时间继续,而且
let
显然也是一个lambda,这可能意味着你必须对它进行一些处理),它使用
let
double
来检查它的调用,并避免在
之前使用
,这是真正的副作用,没有设置变量用于规格


@Zettetic做了一个很有见地的评论,说你不是在测试行为。我并不反对使用rspec来做更多的单元测试风格的事情(准则被打破),但是您可能会问,如果没有调用一个真正的代码块,那么当使用该代码块时,以后的测试将如何通过?在某种程度上,我甚至不确定您是否需要检查块是否被调用,但只有您知道。

let
let相比,code>是初始化规格中使用的值的更好方法。看见我很确定您需要一个设置了期望值的
双精度
(mock)。然后在其他规范中,用实际代码替换
这是双精度。。。这一切如何符合我的问题?我很想知道更多关于这里更大背景的信息。这似乎是在测试实现,而不是行为,这通常是您想要避免的。谢谢您宝贵的评论!我在编辑中对我的问题做了一些解释。
let
let相比,code>是初始化规格中使用的值的更好方法。看见我很确定您需要一个设置了期望值的
双精度
(mock)。然后在其他规范中,用实际代码替换
这是双精度。。。这一切如何符合我的问题?我很想知道更多关于这里更大背景的信息。这似乎是在测试实现,而不是行为,这通常是您想要避免的。谢谢您宝贵的评论!我对我的问题做了一些解释。谢谢你的回答。效果非常好。我只需将
let(:node_块)
中对
double
的调用包装到
Proc
中,因为这是
node.new所必需的。还感谢您向我指出有关测试实现和行为的疑问。当我的代码被重构时,我可能现在应该重构我的测试;-)我可能很狡猾,值得再问一个问题,但我会稍后再问。上述@zettec评论的澄清将在稍后进行;-)谢谢你的回答。效果非常好。我只需将
let(:node_块)
中对
double
的调用包装到
Proc
中,因为这是
node.new所必需的。还感谢您向我指出有关测试实现和行为的疑问。当我的代码被重构时,我可能现在应该重构我的测试;-)我可能很狡猾,值得再问一个问题,但我会稍后再问。cl
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