What's the best way to unit test protected & private methods in Ruby?

后端 未结 16 617
被撕碎了的回忆
被撕碎了的回忆 2020-12-12 10:47

What\'s the best way to unit test protected and private methods in Ruby, using the standard Ruby Test::Unit framework?

I\'m sure somebody will pipe up a

16条回答
  •  陌清茗
    陌清茗 (楼主)
    2020-12-12 11:28

    instance_eval() might help:

    --------------------------------------------------- Object#instance_eval
         obj.instance_eval(string [, filename [, lineno]] )   => obj
         obj.instance_eval {| | block }                       => obj
    ------------------------------------------------------------------------
         Evaluates a string containing Ruby source code, or the given 
         block, within the context of the receiver (obj). In order to set 
         the context, the variable self is set to obj while the code is 
         executing, giving the code access to obj's instance variables. In 
         the version of instance_eval that takes a String, the optional 
         second and third parameters supply a filename and starting line 
         number that are used when reporting compilation errors.
    
            class Klass
              def initialize
                @secret = 99
              end
            end
            k = Klass.new
            k.instance_eval { @secret }   #=> 99
    

    You can use it to access private methods and instance variables directly.

    You could also consider using send(), which will also give you access to private and protected methods (like James Baker suggested)

    Alternatively, you could modify the metaclass of your test object to make the private/protected methods public just for that object.

        test_obj.a_private_method(...) #=> raises NoMethodError
        test_obj.a_protected_method(...) #=> raises NoMethodError
        class << test_obj
            public :a_private_method, :a_protected_method
        end
        test_obj.a_private_method(...) # executes
        test_obj.a_protected_method(...) # executes
    
        other_test_obj = test.obj.class.new
        other_test_obj.a_private_method(...) #=> raises NoMethodError
        other_test_obj.a_protected_method(...) #=> raises NoMethodError
    

    This will let you call these methods without affecting other objects of that class. You could reopen the class within your test directory and make them public for all the instances within your test code, but that might affect your test of the public interface.

提交回复
热议问题