396 Stimmen

Verwendung von Mockito zum Nachahmen von Klassen mit generischen Parametern

Gibt es eine saubere Methode der Spotting eine Klasse mit generischen Parametern? Angenommen, ich muss eine Klasse nachbilden Foo<T> die ich an eine Methode übergeben muss, die eine Foo<Bar> . Ich kann das Folgende leicht tun:

Foo mockFoo = mock(Foo.class);
when(mockFoo.getValue).thenReturn(new Bar());

Angenommen, getValue() gibt den generischen Typ zurück T . Aber das wird Kätzchen haben, wenn ich es später in eine Methode übergebe und erwarte Foo<Bar> . Ist das Gießen die einzige Möglichkeit, dies zu tun?

12voto

vogella Punkte 22056

Mit JUnit5 ist es meiner Meinung nach am besten, @ExtendWith(MockitoExtension.class) mit @Mock im Methodenparameter oder dem Feld zu verwenden.

Das folgende Beispiel zeigt dies anhand von Hamcrest-Matchern.

package com.vogella.junit5;                                                                    

import static org.hamcrest.MatcherAssert.assertThat;                                           
import static org.hamcrest.Matchers.hasItem;                                                   
import static org.mockito.Mockito.verify;                                                      

import java.util.Arrays;                                                                       
import java.util.List;                                                                         

import org.junit.jupiter.api.Test;                                                             
import org.junit.jupiter.api.extension.ExtendWith;                                             
import org.mockito.ArgumentCaptor;                                                             
import org.mockito.Captor;                                                                     
import org.mockito.Mock;                                                                       
import org.mockito.junit.jupiter.MockitoExtension;                                             

@ExtendWith(MockitoExtension.class)                                                            
public class MockitoArgumentCaptureTest {                                                      

    @Captor                                                                                    
    private ArgumentCaptor<List<String>> captor;                                               

    @Test                                                                                      
    public final void shouldContainCertainListItem(@Mock List<String> mockedList) {            
        var asList = Arrays.asList("someElement_test", "someElement");                         
        mockedList.addAll(asList);                                                             

        verify(mockedList).addAll(captor.capture());                                           
        List<String> capturedArgument = captor.getValue();                                     
        assertThat(capturedArgument, hasItem("someElement"));                                  
    }                                                                                          
}                                                                                              

Voir https://www.vogella.com/tutorials/Mockito/article.html für die erforderlichen Maven/Gradle-Abhängigkeiten.

9voto

M. Justin Punkte 8707

Wie in den anderen Antworten erwähnt, gibt es keine gute Möglichkeit, die mock() & spy() Methoden direkt ohne unsicheren Generikazugriff und/oder Unterdrückung von Generikawarnungen.

Derzeit gibt es ein offenes Problem im Mockito-Projekt ( #1531 ), um die Unterstützung für die Verwendung der mock() & spy() Methoden ohne generische Warnungen. Das Problem wurde im November 2018 eröffnet, aber es gibt keine Hinweise darauf, dass es priorisiert wird. In den Kommentaren eines Mockito-Mitarbeiters zu diesem Thema heißt es:

Angesichts der Tatsache, dass .class nicht gut mit Generika zusammenspielt, glaube ich nicht, dass es eine Lösung gibt, die wir in Mockito umsetzen können. Sie können bereits @Mock (die JUnit5-Erweiterung erlaubt auch Methodenparameter @Mock s) und das sollte eine geeignete Alternative sein. Daher können wir dieses Problem offen halten, aber es ist unwahrscheinlich, dass es jemals behoben wird, da @Mock ist eine bessere API.

5voto

xilef Punkte 1815

JUnit5 : verwenden @ExtendWith(MockitoExtension.class) auf die Testklasse und fügen Sie dann dieses Feld hinzu:

@Mock
Foo<Bar> barMock;

4voto

qza Punkte 569

Hier ist ein interessanter Fall: Die Methode empfängt eine generische Sammlung und gibt eine generische Sammlung desselben Basistyps zurück. Zum Beispiel:

Collection<? extends Assertion> map(Collection<? extends Assertion> assertions);

Diese Methode kann mit einer Kombination aus dem Mockito anyCollectionOf Matcher und dem Answer.

when(mockedObject.map(anyCollectionOf(Assertion.class))).thenAnswer(
     new Answer<Collection<Assertion>>() {
         @Override
         public Collection<Assertion> answer(InvocationOnMock invocation) throws Throwable {
             return new ArrayList<Assertion>();
         }
     });

0voto

范仲毅 Punkte 1

Warum nicht mit Spionage

var mock = spy(new Foo<Bar>());
when(mockFoo.getValue()).thenReturn(new Bar());

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