Como testar métodos privados?

Hoje, no blog Nome do Jogo de Carlos Brando, saiu um post falando sobre como testar métodos privados. Uma outra maneira é tornar todos os métodos públicos, sem adicionar nenhum outro.

Basta adicionar o trecho abaixo em seu arquivo test/test_helper.rb ou spec/spec_helper.rb

1
2
3
4
5
6
def turn_public_methods clazz
  clazz.class_eval do
    private_instance_methods.each { |instance_method| public instance_method }
    private_methods.each { |method| public_class_method method }
  end
end

Um exemplo:

1
2
3
4
5
6
7
8
9
10
11
12
#File spec/my_model_spec.rb
require File.dirname(__FILE__) + '/../spec_helper'
describe MyModel do
  before(:each) do
    turn_public_methods(MyModel)
    @mymodel = MyModel.new
  end

  describe "Verify a private method" do
    @mymodel.private_method_name.should_not be_nil
  end
end

Atualização #1

Conforme o comentário de Rafael Muller, resolvi adicionar a comparação apresentada por Evan Phoenix e esta solução.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
### Versão do Evan
class NinjaTest < Test::Unit::TestCase
  def test_should_punish_sloppy_coders
    @ninja = Ninja.new
    def @ninja.flog_publicly(*args)
      kill(*args)
    end
    assert_equal "3 victims are no longer with us.", @ninja.flog_publicly(3)
  end
end

### Versão do Tino ;)
class NinjaTest < Test::Unit::TestCase
  def setup
    turn_methods_public(Ninja);
  end

  def test_should_punish_sloppy_coders
    @ninja = Ninja.new
    assert_equal "3 victims are no longer with us.", @ninja.kill(3)
  end
end

Para mim, um pouco mais limpo o teste, mas gosto é gosto! :)