Monday, November 12, 2007

Ruby: Testing Private Methods

Jason Rudolph recently wrote about Testing Private Methods in Ruby. Before I continue, it's probably a good idea to note that I rarely test private methods. I prefer to test through the public API. However, there are times when life is easier if you write a few tests for a private method or two.

The solution highlighted by Jason (original implementation from Evan Phoenix) is nice from a maintainability perspective since it encapsulates changing the behavior of the class within the test. However, it's a bit verbose for my taste.

Reading the entry I couldn't help but think that gaining temporary access to a private method for testing seems like something that can be handled by a general solution instead.

Here's how I would have solved the problem.

require 'rubygems'
require 'dust'
require 'test/unit'

class Ninja
private
def kill(num_victims)
"#{num_victims} victims are no longer with us."
end
end

class Class
def publicize_methods
saved_private_instance_methods = self.private_instance_methods
self.class_eval { public *saved_private_instance_methods }
yield
self.class_eval { private *saved_private_instance_methods }
end
end

unit_tests do
test "kill returns a murder string" do
Ninja.publicize_methods do
assert_equal '3 victims are no longer with us.', Ninja.new.kill(3)
end
end
end
Post a Comment