2013-04-06 51 views
16

我通过创建一个扩展到库类的子类来扩展现有的库。如何使用rspec在ruby中嘲讽超级?

在子类中,我能够在initialize方法中测试大部分功能,但无法模拟super调用。子类看起来像下面的东西。

class Child < SomeLibrary 
    def initialize(arg) 
     validate_arg(arg) 
     do_something 
     super(arg) 
    end 

    def validate_arg(arg) 
     # do the validation 
    end 

    def do_something 
     @setup = true 
    end 
end 

我怎么能写RSpec的测试(与摩卡),这样我可以嘲笑super通话?请注意,我正在Child类中测试initialize方法的功能。当我提供额外参数时,是否必须创建单独的代码路径,该路径不会调用super

回答

15

你不能模拟super,你不应该。当你嘲笑某件事情时,你正在验证是否收到了特定的消息,并且super不是一条消息 - 它是一个关键字。

相反,如果缺少super调用,请找出该类的哪些行为将会发生变化,并编写一个演示和验证该行为的示例。

+1

这是否意味着我不能写初始化RSpec的测试?为初始化方法编写单元测试是一种不好的做法吗?顺便说一下,我正在扩展数据库连接器库。如果我不写单元测试,但写集成测试,我认为它是奇怪的,如果rspec测试需要连接到真正的数据库。 – 2013-04-07 06:17:57

+0

为什么我们不能嘲笑超级,这对我没有意义。这样做似乎很有用,可以单独正确地测试初始化​​行为,而且super是发送给类实例的消息,不是吗? – 2013-10-21 08:58:57

+1

不,'super'不是发送给类实例的消息。我意识到没有任何ruby元编程构造可以使这成为可能,即使它是,我仍然不相信这是一个好主意。 – 2013-10-21 16:49:45

1

一个很好的方法来测试,这是设置由超采取了一些行动的预期 - 例如:

class Some::Thing < Some 
def instance_method 
    super 
end 
end 

和超类:

class Some 
    def instance_method 
    another_method 
    end 

    def self.another_method # not private! 
    'does a thing' 
    end 
end 

现在测试:

describe '#instance_method' do 
    it 'appropriately triggers the super class method' do 
     sawm = Some::Thing.new 
     expect(sawm).to receive(:another_method) 
     sawm.instance_method 
    end 
end 

所有这些决定了超级被称为超类

此模式的用处取决于您如何构建您的测试/通过应用super方法对孩子/派生类的突变有何期望。

而且 - 狠抓classinstance方法,你将需要调整allowsexpects相应

因人而异