it-swarm.com.de

Private Methode in Ruby (rspec) testen

Ja, ich weiß, dass das Testen privater Methoden keine gute Idee ist (und ich habe diesen Thread gelesen - http://www.Ruby-forum.com/topic/197346 - und einige andere)

Aber wie kann ich den folgenden Code testen?

Ich benutze xmpp4r. In meiner öffentlichen Methode #listen Erhalte ich Jabber-Nachrichten wie folgt:

def listen
  @client.add_message_callback do |m|
    do_things_with_message(m)
  end
end

private
def do_things_with_message(m)
  #
end

#add_message_callback - führt einen Block aus, wenn eine Nachricht kommt (in einem anderen Thread)

Das Testen der #listen - Methode ist schwierig und es testet xmpp4r mehr als meine #do_things_with_message - Methode.

Wie mache ich alles richtig und teste #do_things_with_message? :) ( http://www.Ruby-forum.com/topic/197346#859664 )

Private Methoden in ein neues Objekt umgestalten Das Wesentliche wäre, wenn ich sie öffentlich mache (und mit einer Methode klasse - es ist sinnlos

EDIT: Dies ist eher eine theoretische Frage zu sauberem Code und den richtigen Tests. In meinem ersten Link argumentieren die Leute, dass die privaten Methoden schlecht testen. Ich möchte nicht mit #send Cheaten, sehe aber auch keine praktikablen Möglichkeiten zur Umgestaltung

44
Andrey

Sie können eine private Methode in Ruby mit der send-Methode aufrufen.

@my_object = MyObject.new
@my_object.send(:do_things_with_message, some_message)

In einem Test würde das ungefähr so ​​aussehen:

it "should do a thing" do
  my_object = MyObject.new
  my_object.send(:do_things_with_message, some_message)
  my_object.thing.should == true
end
91
Andrew Hubbs

Abgesehen von der Frage, ob Sie sollten eine private Methode testen, ist es sehr gut möglich, in Ruby, um eine private Methode vorübergehend zu veröffentlichen. Ich meine Folgendes:

# Metaprogrammatical magic to temporarily expose
# a Class' privates (methods).
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

Du würdest publicize_methods so was:

ClassToTest.publicize_methods do
  ...
  do_private_things_with_message(m).should ???
  ...
end
13
buruzaemon

Sie haben diesen Gedanken wahrscheinlich in allen Ressourcen gehört, die Sie erwähnen, aber der richtige "theoretische" Weg, dies zu tun, wäre, zu testen, dass @client empfängt add_message_callback, und testen Sie dann indirekt Ihre privaten Methoden mit Integrationstests. Der springende Punkt beim Unit-Testen ist, dass Sie die Implementierung ändern können und Ihre Tests trotzdem erfolgreich sind

3
enthrops