2010-11-11 66 views
45

我有一個私人方法的模型,我想用RSpec規範,
你通常怎麼做? 你只測試調用私人方法嗎?
還是spec私人的?如果是這樣,你會怎麼做?如何規範私人方法

回答

109

我總是採取這種方法:我想測試我的類公開的API公開的API。

如果你有私有方法,你只能從公開的方法中調用它們來暴露給其他類。因此,如果您測試這些公共方法在所有條件下按預期工作,您也證明了他們使用的私有方法也可以工作。

我承認我遇到了一些特別複雜的私人方法。在你想測試他們極端的情況下,你可以這樣做:

@obj.send(:private_method) 
+1

感謝您的幫助,我同意測試公開的方法證明私人的作品也是如此。這就是說,我真的想測試私有方法,你的解決方案就像一個魅力,謝謝! – Mike 2010-11-11 13:25:28

+2

這是另一個有趣的方法http://kailuowang.blogspot.com/2010/08/testing-private-methods-in-rspec.html – gucki 2012-02-14 09:58:10

+1

我在我的模型中有一個before_save掛鉤,它通過一個私有的私有令牌保存到數據庫'make_private_token'方法。 'make_private_token'方法使用公共類方法,而不是其他方式,所以我可以測試它的唯一方法是使用'send'方法。沒有看到任何「極端」的... – Starkers 2014-01-27 22:54:43

6

對於需要代碼覆蓋率的私有方法(暫時或永久),使用rspec-context-private gem暫時使私有方法的一個範圍內公開。

gem 'rspec-context-private' 

它通過向項目添加共享上下文來工作。

RSpec.shared_context 'private', private: true do 

    before :all do 
    described_class.class_eval do 
     @original_private_instance_methods = private_instance_methods 
     public *@original_private_instance_methods 
    end 
    end 

    after :all do 
    described_class.class_eval do 
     private *@original_private_instance_methods 
    end 
    end 

end 

然後,如果你通過:private作爲元數據爲describe塊,私有方法將是範圍內公開。

class Example 
    private def foo 
    'bar' 
    end 
end 

describe Example, :private do 
    it 'can test private methods' do 
    expect(subject.foo).not eq 'bar' 
    end 
end 
+0

我不知道你是否繼續維護這個gem,但是你的文檔沒有關於聲明shared_context的代碼塊。所以我無法簡單地通過閱讀文檔來實現它。加入這個區塊後,它按預期工作。 – istrasci 2016-07-20 16:46:03

0

如果你想測試一個私有方法的期待,接受的答案將沒有真正的工作(至少不是我所知道的,所以我就應該加以修正就這一點)。我做了什麼,而不是甚至filthier - 在測試本身,只是通過重新定義它暴露方法:

def object_to_test.my_private_method 
    super 
end 

工程上的Ruby 1.8,不能對任何較新的運行時的評論。