RSpec – 测试是否使用之前定义的块调用块

我最近问过如何在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 

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

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

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


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

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

可能我现在应该重构我的测试并使用模拟使它们成为测试行为而不是实现。 然而,为了一些mixins和动态处理发送给对象的消息,它会有点棘手。 现在,这些测试的结果在我脑海里有点模糊;-)

无论如何,你的答案和评论帮助我更好地理解RSpec如何工作,并解释了为什么我要做的事情看起来好像它不适合RSpec。

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

 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来做更多unit testing样式的东西(指导方针被破坏),但你可能会问,如果没有调用那个块,那么在使用真正的代码块时,测试将如何通过? 在某种程度上,我甚至不确定你是否需要检查块被调用,但只有你知道。