133 votes

Ce qui ' s le meilleur moyen d’unité de tester les méthodes protégées & privés dans Ruby ?

Quel est le meilleur moyen de test de l'unité méthodes protégées et privées en Ruby, en utilisant le standard de Ruby Test::Unit - cadre?

Je suis sûr que quelqu'un va la pipe et dogmatiquement affirmer que "vous ne devriez unité de test de méthodes publiques; si elle a besoin de tests unitaires, il ne devrait pas être protégé ou privé de la méthode", mais je ne suis pas vraiment intéressé dans le débat. J'ai plusieurs méthodes qui sont protégées ou privées pour les bonnes raisons valables, ces privé/protégé méthodes sont moyennement complexe, et les méthodes publiques de la classe dépendent de ces protected/private méthodes fonctionne correctement, donc j'ai besoin d'un moyen de tester le protected/private méthodes.

Une chose de plus... en général j'ai mis toutes les méthodes d'une classe donnée dans un fichier, et les tests unitaires pour la classe dans un autre fichier. Idéalement, j'aimerais que toute la magie pour mettre en œuvre cette "unité de test des méthodes protégées et privées" fonctionnalité dans l'unité de test de fichier, pas le fichier source principal, afin de garder le fichier source principal aussi simple et directe que possible.

134voto

James Baker Points 2936

Vous pouvez ignorer l’encapsulation avec la méthode d’envoi :

Il s’agit d’une « fonction » de Ruby. :)

Il y avait débat interne au cours du développement de Ruby 1.9 qui considérés comme ayant respecte la vie privée et l’ignorer, mais en fin de compte, rien n’a changé dans Ruby 1.9. Ignorer les commentaires ci-dessous discuter `` et casser des choses.

71voto

Will Sargent Points 2147

Voici un simple moyen si vous utilisez RSpec :

31voto

Aaron Hinni Points 7879

Vient de réouvrir la classe dans votre fichier de test, et de redéfinir la méthode ou les méthodes publiques. Vous n'avez pas à redéfinir les entrailles de la méthode elle-même, vient de passer le symbole dans l' public appel.

Si vous classe d'origine est définie comme ceci:

class MyClass

  private

  def foo
    true
  end
end

Dans vous fichier de test, il suffit de faire quelque chose comme ceci:

class MyClass
  public :foo

end

Vous pouvez passer plusieurs symboles public si vous souhaitez exposer plus des méthodes privées.

public :foo, :bar

10voto

rampion Points 38697

instance_eval() peut vous aider:

--------------------------------------------------- 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

Vous pouvez l'utiliser pour accéder privé des méthodes et des variables d'instance directement.

Vous pourriez également envisager d'utiliser des send(), qui sera également vous donner accès à des privés et protégés méthodes (comme James Baker suggéré)

Alternativement, vous pouvez modifier la métaclasse de votre test de l'objet pour le rendre privé/protégé méthodes public juste pour cet objet.

	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

Cela vous permettra d'appeler ces méthodes, sans affecter les autres objets de cette classe. Vous pourrait rouvrir la classe à l'intérieur de votre répertoire de test et de les rendre publiques pour tous les les instances à l'intérieur de votre code de test, mais qui pourrait affecter votre test de l'interface publique.

9voto

Scott Points 2453

Je l’ai fait dans le passé consiste :

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X