2014-01-10 7 views
9

Die Java-Klasse (genannt ServiceCaller) Ich möchte Test hat dies zu injizieren:Wie mehrere spottet der gleichen Schnittstelle

@Autowired @Qualifier(value="serviceA") 
SomeService serviceA; 

@Autowired @Qualifier(value="serviceB") 
SomeService serviceB; 

(es gibt eine doWork() Methode, die einen Zustand überprüfen wird und rufen entweder A oder B) .

Wie injiziere ich jeden Service in die entsprechende Variable?

Mein Junit hat diese:

@InjectMocks ServiceCaller classUnderTest = new ServiceCaller(); 

@Mock SomeService mockServiceA; 
@Mock SomeService mockServiceB; 

Doch wenn ich meine Tests ausführen, dass Service A/B unter dem korrekten Zustand genannt zu überprüfen, ich Null-Zeiger erhalten, wie der Schein injiziert worden ist.

Offensichtlich ist es wegen mehrerer Abhängigkeiten auf der gleichen Schnittstelle (SomeService). Gibt es eine Möglichkeit, das Qualifikationsmerkmal anzugeben, wenn der Schein-Service deklariert wird? Oder muss ich Setter für die Abhängigkeiten haben und die altmodische Art einstellen?

Antwort

11

Es sollte genug sein, um Ihre Mocks serviceA und serviceB zu nennen. Von Mockito documentation:

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

In Ihrem Beispiel:

@InjectMocks ServiceCaller classUnderTest; 

@Mock SomeService serviceA; 
@Mock SomeService serviceB; 

Beachten Sie, dass es nicht notwendig ist, manuell Klasseninstanz zu erstellen, wenn @InjectMocks verwenden.

Nichtsdestotrotz bevorzuge ich persönlich das Einfügen von Abhängigkeiten mit Konstruktor. Es macht es einfacher, Mocks in Tests zu injizieren (rufen Sie einfach einen Konstruktor mit Ihren Mocks auf - ohne Reflection Tools oder @InjectMocks (was nützlich ist, aber einige Aspekte verbirgt)). Zusätzlich wird mit TDD deutlich sichtbar, welche Abhängigkeiten für die getestete Klasse benötigt werden und auch IDE kann Ihre Konstruktor-Stubs erzeugen.

Spring Framework unterstützt vollständig Konstruktor Injektion:

Sie "Name" Eigenschaft definieren Ihre Instanz wie folgt verwenden können
@Mock SomeService serviceA; 
@Mock SomeService serviceB; 

//in a setup or test method 
ServiceCaller classUnderTest = new ServiceCaller(serviceA, serviceB); 
+0

Brilliant! Hoffte, es wäre so einfach und es funktioniert. Danke Szpak !!! – shuttsy

+0

In Ihrer letzten Codezeile können Sie schreiben: @InjectMocks ServiceCaller classUnderTest; – Vjeetje

+0

Ja, aber bitte lesen Sie den Text in der Mitte meiner Antwort, um zu erfahren, warum ich normalerweise einen Konstruktor in Tests explizit aufrufen möchte. –

1

:

@Mock(name="serviceA") SomeService serviceA; 
@Mock(name="serviceB") SomeService serviceB; 

@Bean 
public class ServiceCaller { 
    private final SomeService serviceA; 
    private final SomeService serviceB; 

    @Autowired 
    public ServiceCaller(@Qualifier("serviceA") SomeService serviceA, 
         @Qualifier("serviceB") SomeService serviceB) { ... } 

    ... 
} 

Dieser Code kann mit getestet werden

+0

Können Sie weitere Einzelheiten angeben, um zu erläutern, wie Ihre Antwort einen Wert hinzufügt, den die akzeptierte Antwort nicht bereits bietet? –

+0

kein anderer besonderer Wert, aber ein anderer Weg – osiris256

Verwandte Themen