725 Stimmen

Unterschied zwischen @Mock und @InjectMocks

Was ist der Unterschied zwischen @Mock und @InjectMocks im Mockito-Framework?

14voto

serup Punkte 3258

Ein "Mocking-Framework", auf dem Mockito basiert, ist ein Framework, das es Ihnen ermöglicht, Mock-Objekte zu erstellen (in alten Begriffen könnten diese Objekte als Schüttel bezeichnet werden, da sie als Schüttel für abhängige Funktionalitäten arbeiten) Mit anderen Worten, ein Mock-Objekt wird verwendet, um das reale Objekt zu imitieren, von dem Ihr Code abhängt. Sie erstellen ein Proxy-Objekt mit dem Mocking-Framework. Durch die Verwendung von Mock-Objekten in Ihren Tests gehen Sie im Grunde von normalen Unittests zu Integrationstests über

Mockito ist ein Open-Source-Test-Framework für Java, das unter der MIT-Lizenz veröffentlicht wurde. Es ist ein "Mocking-Framework", das es Ihnen ermöglicht, schöne Tests mit einer sauberen und einfachen API zu schreiben. Es gibt viele verschiedene Mocking-Frameworks im Java-Bereich, jedoch gibt es im Wesentlichen zwei Haupttypen von Mock-Objekt-Frameworks, solche, die über Proxy implementiert werden und solche, die über Klassen-Remapping implementiert werden.

Dependency Injection-Frameworks wie Spring ermöglichen es Ihnen, Ihre Proxy-Objekte einzufügen, ohne Code zu ändern. Das Mock-Objekt erwartet, dass eine bestimmte Methode aufgerufen wird, und gibt ein erwartetes Ergebnis zurück.

Die @InjectMocks Annotation versucht, die Testobjektinstanz zu instanziieren und injiziert Felder, die mit @Mock oder @Spy annotiert sind, in private Felder des Testobjekts.

Der MockitoAnnotations.initMocks(this) Aufruf setzt das Testobjekt zurück und initialisiert die Mocks neu, also denken Sie daran, dies bei Ihrer @Before / @BeforeMethod Annotation zu haben.

14voto

Angelin Nadar Punkte 8458

Auch wenn die oben genannten Antworten abgedeckt haben, habe ich gerade versucht, winzige Details hinzuzufügen, die mir fehlen. Der Grund dafür (Das Warum).

Bildbeschreibung hier eingeben


Illustration:

Sample.java
---------------
    public class Sample{
        DependencyOne dependencyOne;
        DependencyTwo dependencyTwo;

        public SampleResponse methodOfSample(){
            dependencyOne.methodOne();
            dependencyTwo.methodTwo();

            ...

            return sampleResponse;
        }
    }

SampleTest.java
-----------------------
@RunWith(PowerMockRunner.class)
@PrepareForTest({ClassA.class})
public class SampleTest{

    @InjectMocks
    Sample sample;

    @Mock
    DependencyOne dependencyOne;

    @Mock
    DependencyTwo dependencyTwo;

    @Before
    public void init() {
        MockitoAnnotations.initMocks(this);
    }

    public void sampleMethod1_Test(){
        //Ordnen Sie die Abhängigkeiten
        DependencyResponse dependencyOneResponse = Mock(sampleResponse.class);
        Mockito.doReturn(dependencyOneResponse).when(dependencyOne).methodOne();

        DependencyResponse dependencyTwoResponse = Mock(sampleResponse.class);
        Mockito.doReturn(dependencyOneResponse).when(dependencyTwo).methodTwo();

        //Rufen Sie die zu testende Methode auf
        SampleResponse sampleResponse = sample.methodOfSample() 

        //Assert

    }
}

Referenz

10voto

tintin Punkte 5414

Ein Vorteil bei dem von @Tom erwähnten Ansatz ist, dass Sie keine Konstruktoren im SomeManager erstellen müssen und somit die Klienten daran hindern, es zu instanziieren.

@RunWith(MockitoJUnitRunner.class)
public class SomeManagerTest {

    @InjectMocks
    private SomeManager someManager;

    @Mock
    private SomeDependency someDependency; // dieser wird in someManager injiziert

    //Sie müssen den SomeManager überhaupt nicht mit dem Standardkonstruktor instanziieren 
    //SomeManager someManager = new SomeManager();    
   //Oder SomeManager someManager = new SomeManager(someDependency);

     //Tests...

}

Ob es eine gute Praxis ist oder nicht, hängt von Ihrem Anwendungsdesign ab.

10voto

dev_2014 Punkte 281

@Mock wird verwendet, um die Referenzen der abhängigen Beans zu deklarieren/mocks, während @InjectMocks verwendet wird, um die Bean zu mocken, für die der Test erstellt wird.

Zum Beispiel:

public class A{

   public class B b;

   public void doSomething(){

   }

}

Test für Klasse A:

public class TestClassA{

   @Mocks
   public class B b;

   @InjectMocks
   public class A a;

   @Test
   public testDoSomething(){

   }

}

10voto

Lahiru Wijesekara Punkte 603

Die @InjectMocks-Annotation kann verwendet werden, um Mock-Felder automatisch in ein Testobjekt einzufügen.

In folgendem Beispiel wurde @InjectMocks verwendet, um die Mock-DatenMap in die dataLibrary einzufügen.

@Mock
Map dataMap;

@InjectMocks
DataLibrary dataLibrary = new DataLibrary();

    @Test
    public void whenUseInjectMocksAnnotation_() {
        Mockito.when(dataMap.get("aData")).thenReturn("aMeaning");

        assertEquals("aMeaning", dataLibrary.getMeaning("aData"));
    }

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X