2013-03-05 7 views
16

Hier ist meine Frage:Wie funktioniert Mockito @InjectMocks?

Ich habe mehrere Web-Services-Klassen zu testen, dass alle ihre Methoden von einem generischen Service erben. Anstatt für jeden einen Komponententest zu schreiben, denke ich, dass ich die Testsuite um funktionale Bereiche (d. H. Drei Gruppen von Testmethoden, von denen sich jede auf einen anderen zugrunde liegenden DAO-Methodenaufruf stützt) unterteilen kann.

Was ich vorschlagen zu tun ist:

@Mock StateDAO mockedStateDao; 
@Mock CountyDAO mockedCountyDao; 
@Mock VisitorDAO mockedVisitorDao; 

dann rufen:

@InjectMocks CountyServiceImpl<County> countyService = new CountyServiceImpl<County>(); 
@InjectMocks StateServiceImpl<State> stateService = new StateServiceImpl<State>(); 
@InjectMocks VisitorServiceImpl<Visitor> visitorService = new VisitorServiceImpl<Visitor>(); 

Wie kann ich sicher sein, dass jeder mockedDAO wird in den richtigen Dienst injiziert werden? Wäre es einfacher alle drei zu autowire (anstatt @InjectMocks zu verwenden)?

Ich verwende Spring, Hibernate und Mockito ...

+0

Wird innerhalb dieses Testklasse tun. – DYezek

+0

Außerdem habe ich die Elemente für @InjectMocks bereits in der Spring Test-Application-Context.xml-Datei (so könnte ich sie automatisch). Nicht sicher über den Unterschied zwischen Autowiring und injizierenden Mocks. – DYezek

+1

Bearbeiten Sie Ihre ursprüngliche Frage, um zusätzlichen Inhalt hinzuzufügen, anstatt Kommentare zu Ihrer Frage zu hinterlassen. – ArtB

Antwort

0

Nevermind, sah online- die InjectMocks Annotation etwas mit der @Mock Annotation als ein Feld behandelt und ist statisch-scoped (Klasse breit), so Ich konnte wirklich nicht garantieren, dass die Mocks zum richtigen Service gehen würden. Dies war ein Denkexperiment, um zu versuchen, den Test auf Feature-Ebene statt auf Klassen-Ebene zu testen. Ich denke, ich werde dieses Zeug mit Spring einfach autowire ...

1

Nun, die statische Methode MockitoAnnotations.initMocks(Object) wird verwendet, um den gesamten Prozess Bootstrap.

Ich weiß nicht genau, wie es funktioniert, da ich nicht den Quellcode durchsucht habe, aber ich würde es so etwas wie dies umzusetzen:

  1. Scannen Sie die vergangen Object ‚s-Klasse für Membervariablen mit der @Mock Annotation.
  2. Erstellen Sie für jede eine Kopie dieser Klasse und legen Sie sie für dieses Mitglied fest.
  3. Scannen Sie die Klasse Object für Elementvariablen mit der @InjectMocks Annotation.
  4. Scannen Sie die Klasse jedes gefundenen Elements für Mitglieder, die mit einem der in (2) erstellten Mock - Objekte injiziert werden können (dh, das Feld ist eine Elternklasse/Schnittstelle oder dieselbe Klasse wie die Mock-Objekte deklariert Klasse) und setzen Sie es auf dieses Mitglied.
19

Nun nikolaus beantworten ist fast richtig, sondern nur an der javadoc von InjectMocks aussehen zu erraten, es enthält mehr Details;)

Für mich ist es seltsam, so viele Service in einem einzigen Test zu haben, es fühlt sich nicht richtig an, als Unit Test oder als Integrationstest. Im Komponententest ist es falsch, weil Sie viel zu viele Mitarbeiter haben, es sieht nicht wie objektorientiert (oder SOLID) aus. Bei Integrationstests ist es komisch, weil der Code, den man bei der Integration mit der DB testet, sich nicht darüber lustig macht.

Für eine schnelle Referenz in 1.9.5 Sie haben:

Mark ein Feld, auf der Injektion durchgeführt werden soll.

Ermöglicht Kurzschreib- und Spionage-Injektion. Minimiert sich wiederholende Schein- und Spionage-Injektionen. Mockito versucht, Mocks nur entweder durch Konstruktorinjektion, Setterinjektion oder Eigenschaftsinjektion der Reihe nach und wie unten beschrieben zu injizieren. Wenn eine der folgenden Strategien fehlschlägt, meldet Mockito keinen Fehler. Das heißt, Sie müssen selbst Abhängigkeiten bereitstellen.

  1. Konstruktoreinspritzung; der größte Konstruktor ausgewählt wird, dann werden Argumente mit Mocks aufgelöst, die nur im Test deklariert sind.

    Hinweis: Wenn Argumente nicht gefunden werden können, wird null übergeben. Wenn nicht vorstellbare Typen gewünscht werden, wird die Konstruktorinjektion nicht stattfinden. In diesen Fällen müssen Sie Abhängigkeiten selbst erfüllen.

  2. Property-Setter-Injektion; Mocks werden zuerst nach Typ aufgelöst, dann, wenn es mehrere Eigenschaften desselben Typs gibt, durch die Übereinstimmung des Eigenschaftsnamens und des Mock-Namens.

    Anmerkung 1: Wenn Sie Objekte mit dem gleichen Typ (oder gleicher Löschung) haben, ist es besser, alle @Mock kommentierten Felder mit den entsprechenden Eigenschaften zu nennen, sonst könnte Mockito verwirrt und Injektion wird nicht passieren.

    Hinweis 2: Wenn die @InjectMocks-Instanz zuvor nicht initialisiert wurde und einen no-arg-Konstruktor hat, wird sie mit diesem Konstruktor initialisiert.

  3. Feldinjektion; Mocks werden zuerst nach Typ aufgelöst, dann, wenn es mehrere Eigenschaften desselben Typs gibt, durch die Übereinstimmung des Feldnamens und des Mock-Namens.

    Anmerkung 1: Wenn Sie Felder mit dem gleichen Typ (oder gleicher Löschung) haben, ist es besser, alle @Mock kommentierten Felder mit den entsprechenden Feldern zu nennen, sonst könnte Mockito verwirrt und Injektion wird nicht passieren.

    Hinweis 2: Wenn die @InjectMocks-Instanz zuvor nicht initialisiert wurde und einen no-arg-Konstruktor hat, wird sie mit diesem Konstruktor initialisiert.

3

Wenn Sie mehrere Dienste und möchten die DAOs mit Mock-Objekte in einer Frühjahr-basierten Umgebung ersetzen, würde ich empfehlen Springockito zu verwenden: https://bitbucket.org/kubek2k/springockito/wiki/Home

die auch hier erwähnt wird: Injecting Mockito mocks into a Spring bean

Ihre Testclass dann könnte wie folgt aussehen:

@RunWith (SpringJUnit4ClassRunner.class) 
@ContextConfiguration (loader = SpringockitoContextLoader.class, locations = {"classpath:/org/example/package/applicationContext.xml"}) 
public class NameOfClassTest { 

    @Autowired 
    @ReplaceWithMock 
    StateDAO mockedStateDao; 

    @Autowired 
    @ReplaceWithMock 
    CountyDAO mockedCountyDao; 

    @Autowired 
    @ReplaceWithMock 
    VisitorDAO mockedVisitorDao; 

In Ihrem @Test oder @Before Methode können Sie Ihre Mocks den Standard Mockito Weg Setup:

Mockito.doReturn(null).when(mockedCountyDao).selectFromDB(); 
Verwandte Themen