2017-05-31 1 views
1

I Frühling KlasseMockito wenn(). ThenReturn() verhält sich nicht wie erwartet, wenn lombok @RequiredArgsConstructor (onConstructor = @__ (@ Autowired)) verwendet wird

@Component 
@RequiredArgsConstructor(onConstructor = @__(@Autowired)) 
class MainServiceImpl implements MainService { 
    private final InternalService internalService; 

    public Set<String> do(String anything) { 
     Set<String> relevent = internalService.finaIntern(anything); 
     return relevent; 
    } 
} 

I Unit Test Fall schreibe sagen haben wie unten

@RunWith(MockitoJUnitRunner.class) 
class TestMainServiceImpl { 

    @InjectMocks 
    private MainServiceImpl service; 

    @Mock 
    InternalService internalService; 

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

    @Test 
    public void testDo() { 
     Set<String> setData = new HashSet<>(); 
     setData.add("ABC"); 
     String a ="a"; 
     when(internalService.finaIntern(any(String.class)) 
            .thenReturn(setData); 
     Set<String> result = service.do(a); 
     assertTrue(!result.isEmpty()); 
    } 

} 

Hier mein Testfall versagt, aber wenn ich letzte Form MainServiceImpl entfernen und eine explizite @Autowired wie unten

tun
@Component 
class MainServiceImpl implements MainService { 
    @Autowired 
    private InternalService internalService; 
    ..... 

Hier bin ich neugierig 1. zu wissen, wie funktioniert mein Testfall passieren, wenn ich Schlüsselwort final entferne 2. Ist es eine gute Praxis @RequiredArgsConstructor zu verwenden, wenn ja, dann wie und ob nicht dann auch, warum?

Vielen Dank im Voraus

+0

Ihr Test macht keinen Sinn ... Sie erstellen einen Mock und injizieren ihn in den Testfall und nicht in den 'MainServiceImpl'. Entweder Sie zeigen nicht den Code, wie Sie verwenden, oder Ihr Code ist wirklich borked. –

+0

@M.Deinum Da ich aus Gründen der Sicherheit hier keinen Code schreiben kann, habe ich ähnliche Klassen eingegeben. Es war ein Schreibfehler. Ich habe es geändert. – MishraJi

+0

Sie haben auch eine Doppel-Init, Sie laufen bereits mit dem 'MockitoJUnitRunner', aber initialisieren Sie sie erneut in Ihrer '@ before'-Methode. Sie müssen sie initiieren (besonders wegen Ihrer letzten Mitglieder). –

Antwort

2

Es hat nichts mit lombok noch Frühling @Autowired Die Kombination aus @RunWith(MockitoJUnitRunner.class) und MockitoAnnotations.initMocks(this); ist das Problem zu tun hat. Entfernen von irgendetwas davon und das Verhalten ist wie erwartet. Du brauchst nicht beide. Tatsächlich existiert MockitoAnnotations.initMocks(this); nur für die Fälle, in denen Sie @RunWith(MockitoJUnitRunner.class) nicht verwenden können, zum Beispiel, wenn Sie SpringRunner.class verwenden müssen.

Hier ist, warum es nicht funktioniert. Zuerst werden alle Ihre Objekte instanziiert. Also sowohl Ihre @Mock erstellt und injiziert in Sie @InjectMock Objekt:

Unten Sie sehen, dass die neue Mock erstellen (mocks[0]), service innerhalb von injectInto und mock sind das gleiche Objekt.

enter image description here

Aber dann geschieht die Initialisierung zum zweiten Mal. So Mockito erstellen Sie ein neues @Mock Objekt, und versucht, es in Ihr @InjectMock Objekt zu injizieren, das bereits instanziiert ist. Aber es ist nicht gelungen, es auf das Feld zu injizieren, solange es endgültig ist. So, hier ist das, was wir nach der zweiten Initialisierung haben:

enter image description here Wie Sie jetzt das Mock-Objekt innerhalb Ihres testClassInstance und der Mock zu Ihrem Objekt unter Test sind verschiedene injizierte sehen.

Was ist mit @RequiredArgsConstructor: Für mich ist es völlig in Ordnung, es so zu verwenden, wie Sie es getan haben.

Verwandte Themen