2013-04-06 53 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相應

因人而異