2016-08-09 116 views
4

Ich verwende Mockito, um Methoden innerhalb meiner Java Anwendung zu testen.Mockto: Wie testen, dass ein Konstruktor aufgerufen wurde?

Wie kann ich testen, dass ein Konstruktor einer genannt wurde?

Ich versuche, ein in etwa so zu tun, überprüfen:

verify(myclass, times(1)).doSomething(anotherObject); 

Aber ich kann nicht den Konstruktor überprüft genannt wurde, da es nicht ein ähnliches Verfahren wie zum Beispiel hat doSomething()

+0

Ähm, Sie können ein Objekt nicht erhalten, wenn Sie seinen Konstruktor nicht nennen; das ist eine Sprachfunktion. –

+1

Bitte erläutern Sie, was Sie meinen – java123999

+0

Sie sollten beschreiben, was Sie tatsächlich testen möchten, dass Sie glauben, Sie müssten einen Konstrukteur verspotten. Ich wäre nicht überrascht, wenn es keinen wirklichen Bedarf dafür gibt. –

Antwort

8

Dies ist mit Mockito nicht möglich, da das erstellte Objekt kein verspottetes Objekt ist. Dies bedeutet auch, dass Sie nichts an diesem neuen Objekt verifizieren können.

Ich habe in der Vergangenheit mit diesem Szenario gearbeitet, indem ich ein Factory verwendet, um das Objekt zu erstellen, anstatt es neu zu erstellen. Sie sind dann in der Lage, das Factory zu verspotten, um das für Ihren Test erforderliche Objekt zurückzugeben.

Ob es Ihnen gefällt, Ihr Design an Ihre Tests anzupassen, bleibt Ihnen überlassen!

+0

Dies scheint die beste Lösung. Ich werde in Zukunft mit einer Factory-Klasse arbeiten, um dieses Problem zu lösen – java123999

+0

Eine Fabrik einzuführen, um eine Einschränkung in der spöttischen Bibliothek zu umgehen ... das ist offensichtlich keine gute Lösung. Stattdessen würde ich vorschlagen, die vermeintliche Notwendigkeit zu vermeiden, die Klasse zu verspotten, die von der SUT instanziiert wird. Normalerweise ist ein besserer Test ohne Mocking möglich. –

0

Ein Konstruktor wird ein Objekt nicht zurückgeben, wenn es fehlgeschlagen ist ... und wenn es fehlschlägt, stürzt das Programm höchstwahrscheinlich ab.

Tough Ich nehme diese es tun würde:

Object obj = null; 

obj = new Object(); 

if (obj == null) { 
    //... Didn't Work 
} else { 
    //... Worked 
} 
+3

OP fragt nicht, wie man überprüft, ob der Konstruktor funktioniert, sondern wie man überprüft, ob tatsächlich ein anderer Code den Konstruktor aufruft. –

1

verify() Methode wartet verspottet Objekt (bereits erstellte Objekt). Und constructor kann nicht auf created object aufgerufen werden.

1

Dies ist mit Mockito nicht möglich und klingt wie ein schlechtes Design.

Sie können eine Fabrik verwenden und sie an das zu testende Objekt übergeben. Danach können Sie die Fabrik leicht verspotten und prüfen, ob die create-Methode aufgerufen wurde.

Durch das direkte Erstellen von Objekten in Ihrem Code machen Sie eine harte Abhängigkeit von konkreten Implementierungen, was den Code schwieriger und manchmal unmöglich macht, Unit-Tests durchzuführen. Dies wird mit Dependency Injection (DI) und Inversion of Control (IoC) adressiert.

0

Sie können den Konstruktor nicht mit Mockito verspotten, aber mit powermockito sollten Sie in der Lage sein, und dann überprüfen Sie es. Setup wäre so etwas wie dies

public class MyClass{ 

    public MyClass(String name){} 

    public void doSomethingUseFul(){ 
     //....... 
    } 

} 

public class Helper { 

    public void goHelp(){ 
     new MyClass("apple").doSomethingUseFul(); 
    } 

} 

// Mock

@RunWith(PowerMockRunner.class) 
    @PrepareForTest(MyClass.class) 
    public class MockMyClass { 
    @InjectMocks 
    private Helper helper; 

     @Test 
     public void testDoSomethingUseFul() { 
      MyClass c = mock(MyClass.class); 
      doNothing().when(c).doSomethingUseFul(); 
      PowerMockito.whenNew(MyClass. class).withArguments(anyString()).thenReturn(c); 
      helper.goHelp(); 
      verifyNew(MyClass.class).withArguments(anyString()) 


     } 
    } 
8

sind Sie tun können, es mit Mockito und PowerMockito.

Sagen Sie bitte ClassUnderTest mit einem Konstruktor

public class ClassUnderTest { 
    String name; 
    boolean condition; 

    public ClassUnderTest(String name, boolean condition) { 
     this.name = name; 
     this.condition = condition; 
     init(); 
    } 

    ... 
} 

Und eine andere Klasse, die das Konstruktor

public class MyClass { 

    public MyClass() { } 

    public void createCUTInstance() { 
     // ... 
     ClassUnderTest cut = new ClassUnderTest("abc", true); 
     // ... 
    } 

    ... 
} 

konnten wir bei der Testklasse ruft ...

(1) verwenden PowerMockRunner und beide Zielklassen in der obigen PrepareForTest Annotation zitieren:

@RunWith(PowerMockRunner.class) 
@PrepareForTest({ ClassUnderTest.class, MyClass.class }) 
public class TestClass { 

(2) abfangen der Konstruktor ein Mockobjekt zurückzukehren:

@Before 
public void setup() { 
    ClassUnderTest cutMock = Mockito.mock(ClassUnderTest.class); 
    PowerMockito.whenNew(ClassUnderTest.class) 
       .withArguments(Matchers.anyString(), Matchers.anyBoolean()) 
       .thenReturn(cutMock); 
} 

(3) Validieren der Konstruktoraufruf:

@Test 
public void testMethod() { 
    // prepare 
    MyClasss myClass = new MyClass(); 

    // execute 
    myClass.createCUTInstance(); 

    // checks if the constructor has been called once and with the expected argument values: 
    String name = "abc"; 
    String condition = true; 
    PowerMockito.verifyNew(ClassUnderTest.class).withArguments(name, condition); 
} 
+0

Ich denke, die Reihenfolge der letzten zwei Zeilen in Ihrer testMethod() sollte vertauschen. so: neuer ClassUnderTest (Name, Bedingung); PowerMockito.verifyNew (ClassUnderTest.class); –

+0

@WillieZ, vielen Dank, dass Sie mich auf diese Testmethode aufmerksam gemacht haben! In Wahrheit wurde dieser vorhergehende letzte Befehl nicht wirklich benötigt. Die ursprüngliche Idee war, den Konstruktoraufruf mit bestimmten spezifischen Argumentwerten in einer zu testenden Methode zu testen, die in der Ausführungsphase aufgerufen wird. Ich habe gerade den Code umgeschrieben, um meine ursprüngliche Absicht auszudrücken. Ich hoffe, es ist jetzt klarer. –