web-dev-qa-db-fra.com

Comment spécifier une méthode privée

J'ai un modèle avec une méthode privée que je voudrais spécifier avec RSpec,
comment faites-vous habituellement? Testez-vous uniquement la méthode appelant la méthode privée?
ou spécifiez également le privé? si oui, comment faites-vous?

54
Mike

Je prends toujours cette approche: je veux tester l'API publique que ma classe expose.

Si vous avez des méthodes privées, vous ne les appelez qu'à partir des méthodes publiques que vous exposez à d'autres classes. Par conséquent, si vous testez que ces méthodes publiques fonctionnent comme prévu dans toutes les conditions, vous avez également prouvé que les méthodes privées qu'elles utilisent fonctionnent également.

J'avoue que j'ai rencontré des méthodes privées particulièrement complexes. Dans ce cas extrême où vous souhaitez les tester, vous pouvez le faire:

@obj.send(:private_method)
117
Ariejan

Pour les méthodes privées qui nécessitent une couverture de code (temporairement ou définitivement), utilisez la rspec-context-private gem pour rendre temporairement des méthodes privées publiques dans un contexte.

gem 'rspec-context-private'

Cela fonctionne en ajoutant un contexte partagé à votre projet.

RSpec.shared_context 'private', private: true do

  before :all do
    described_class.class_eval do
      @original_private_instance_methods = private_instance_methods
      public *@original_private_instance_methods
    end
  end

  after :all do
    described_class.class_eval do
      private *@original_private_instance_methods
    end
  end

end

Ensuite, si vous passez :private en tant que métadonnées d'un bloc describe, les méthodes privées seront publiques dans ce contexte.

class Example
  private def foo
    'bar'
  end
end

describe Example, :private do
  it 'can test private methods' do
    expect(subject.foo).not eq 'bar'
  end
end
6
barelyknown

Si vous souhaitez tester une attente sur une méthode privée, la réponse acceptée ne fonctionnera pas vraiment (du moins pas à ma connaissance, je suis donc ouvert à la correction sur ce point). Ce que j'ai fait à la place est encore plus sale - dans le test lui-même, il suffit d'exposer la méthode en la redéfinissant:

def object_to_test.my_private_method
  super
end

Fonctionne sur Ruby 1.8, ne peut commenter aucun des nouveaux runtimes.

0
Nathan Crause