2010-11-11 34 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,不能对任何较新的运行时的评论。