2013-05-06 8 views
5

Ich habe die folgende Klasse:PowerMockito: Wie man Methoden vorspiegelt, die vom Erbauer genannt werden?

public class Foo { 

    public Foo() { 
    initField1(); 
    initField2(); 
    initField3(); 
    } 

} 

Ich brauche das Verhalten zu ändern (zu verspotten) initField1() und initField3() für sie nichts oder etwas anderes machen tun, dass sie tatsächlich tun. Ich bin daran interessiert, den eigentlichen Code von initField2() auszuführen.

Ich mag folgenden Test schreiben:

Foo foo = new Foo(); 
assertTrue(foo.myGet()); 

myGet() ein Attribut von Foo zurückgibt, die durch initField2() berechnet wurde.

Die Methoden initField() sind natürlich privat.

Wie kann ich so etwas tun?

Vielen Dank für Ihre Hilfe und beste Grüße.

Antwort

-1

Ich denke, es ist etwas falsch in dem, was Sie tun möchten.

Soweit ich verstehe, soll ein spöttisches Framework wie Mockito oder PowerMock die Interaktion zwischen dem zu testenden Objekt und seinen Abhängigkeiten verspotten.

Wie ich deine Frage verstehe, willst du einen Teil des Objektverhaltens verspotten und den Rest davon testen.

In Ihrem Fall sollten Sie etwas testen, die nie passieren wird, wie initField2() wird nie ohne Anrufe zu initField1() und initField3()

Wenn der Grund, warum Sie initField1() und initField3 ist, weil diese nennen wollen nicht genannt werden Methoden interagieren mit anderen Objekten, oder Dateisystem oder DB, dann sollten Sie eher die Abhängigkeiten über Konstruktor Argument oder kommentierte Setter injizieren, und nur Mocks für Ihre Tests injizieren. Und um Ihr Objekt mit seinen ordnungsgemäß eingerichteten Abhängigkeiten zu instanziieren, verwenden Sie das Factory-Muster, das Builder-Muster oder, noch besser, ein Abhängigkeits-Injection-Framework wie das von Spring oder Google Guice.

Wenn der Grund, warum Sie d'ont initField1() und initField3 nennen wollen, weil sie mit verschiedenen Business-Logik in Ihrem Objekt beschäftigen, dann riecht diese (wie in http://martinfowler.com/books/refactoring.html) wie Sie die einzige Verantwortung Prinzip sind zu brechen, und Sie sollten Refaktor.

+0

Dies ist Legacy-Code. Ich möchte die zu testende Klasse nicht modifizieren, indem ich einen neuen Konstruktor schreibe, der zum Beispiel Argumente akzeptiert. Ich möchte nur 'initField2()' ausgeführt werden, da es für das Setzen des Feldes verantwortlich ist, das ich testen möchte. Ich bin nicht daran interessiert, den Rest der Logik des Konstruktors zu testen. –

+0

Mockito soll die Interaktion spotten, PowerMock soll teilweise interne Abläufe einer Klasse für Legacy-Code nachahmen, also ist diese Antwort einfach falsch. – eis

5

alles bedenkt, kann in Legacy-Code passieren :) Sie PowerMock verwenden können Methoden zu unterdrücken, wie in http://code.google.com/p/powermock/wiki/SuppressUnwantedBehavior

beschrieben
import static org.powermock.api.support.membermodification.MemberMatcher.methods; 
import static org.powermock.api.support.membermodification.MemberModifier.suppress; 

@RunWith(PowerMockRunner.class) 
@PrepareForTest(Foo.class) 
public class FooTest { 

    @Test 
    public void testSuppressMethod() throws Exception { 
     suppress(methods(Foo.class, "initField1", "initField3")); 
     Foo foo = new Foo(); 
    } 
} 

Dennoch sollten Sie die Klasse erneut Faktor, nachdem Sie ausreichend Testabdeckung für ihn haben .

+0

Vielen Dank. Es funktioniert jetzt! Eine weitere Frage, wie kann ich überprüfen, dass 'initField2()' aufgerufen wurde? Ich dachte darüber nach, mein neues Foo zu spionieren, aber es gibt eigentlich keine Interaktion damit, 'verifyPrivate (foo) .invoke (initField2)' hilft nicht. –

+0

@JulienCollah werden Sie es indirekt testen, indem Sie überprüfen, dass 'foo.myGet()' einen korrekten Wert zurückgibt. –