Testing private class methods in Ruby

I generally make a point of not unit testing private methods however in some circumstance I find it necessary to do so. One example of this is when a class method is to be documented in the API of a library, only for use when declaring a descendent class (the Rails validates_* macros could be private for example).

Testing of private instance methods has already been documented by Jay Fields, however testing private class methods requires a little more work:


class Class
  def publicize_private_class_methods
    saved_instance_methods = (class << self; private_instance_methods.sort; end)
    saved_instance_methods.each { |method| public_class_method method }
    yield self
  ensure
    saved_instance_methods.each { |method| private_class_method method }
  end
end

This allows you to do the following:


class Foo
  class << self
    private

    def foo
      'bar'
    end
  end
end

Foo.publicize_private_class_methods do |klass|
  assert_equal 'bar', klass.foo
end

The same would work for protected methods by changing all instances of the word ‘private’ with ‘protected’.

All this could probably be merged into the original method by Jay, however I will leave that as an exercise for the reader.

Published by

Jamie

Hi, I am the Managing Director of SonicIQ Limited in the UK. I have been working in the web development industry since 1999 and have been running SonicIQ since 2001. Currently Ruby On Rails is my preferred development platform. I am experienced in designing with web standards, HTML5, CSS3 and Javascript.

4 thoughts on “Testing private class methods in Ruby”

  1. Why not just use class_eval to call the private methods?

    MyClass.class_eval { private_class_method }

    That will return whatever the method returns.

  2. Amos,

    That doesn’t work as private_class_method is used to make a method private, not call it. I wish it was that easy (maybe I’m missing something?).

    In any case I would rather wrap the functionality up in a single method of Class for cleanliness.

    Jamie

  3. I didn’t mean private_class_method like the ruby method. Sorry. I meant a private class method. Maybe I should have put private_class_method_foo. Sorry for the confusion.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>