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?

370voto

John Paulett Punkte 15210

Ich glaube, Sie müssen es gießen, aber es sollte nicht allzu schlimm sein:

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

356voto

Marek Kirejczyk Punkte 5014

Eine andere Möglichkeit, dies zu umgehen, ist die Verwendung von @Mock stattdessen eine Bemerkung. Funktioniert nicht in allen Fällen, sieht aber viel attraktiver aus :)

Hier ist ein Beispiel:

@RunWith(MockitoJUnitRunner.class)
public class FooTests {

    @Mock
    public Foo<Bar> fooMock;

    @Test
    public void testFoo() {
        when(fooMock.getValue()).thenReturn(new Bar());
    }
}

Les MockitoJUnitRunner initialisiert die Felder, die mit @Mock .

58voto

dsingleton Punkte 926

Sie können jederzeit eine Zwischenklasse/Schnittstelle erstellen, die den von Ihnen gewünschten generischen Typ erfüllt. Wenn Foo beispielsweise eine Schnittstelle wäre, könnten Sie in Ihrer Testklasse die folgende Schnittstelle erstellen.

private interface FooBar extends Foo<Bar>
{
}

In Situationen, in denen Foo ein nicht abschließend können Sie die Klasse einfach mit folgendem Code erweitern und das Gleiche tun:

public class FooBar extends Foo<Bar>
{
}

Dann können Sie jedes der oben genannten Beispiele mit dem folgenden Code verwenden:

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

24voto

acdcjunior Punkte 123383

Erstellen einer Test-Utility-Methode . Besonders nützlich, wenn Sie es mehr als einmal brauchen.

@Test
public void testMyTest() {
    // ...
    Foo<Bar> mockFooBar = mockFoo();
    when(mockFooBar.getValue).thenReturn(new Bar());

    Foo<Baz> mockFooBaz = mockFoo();
    when(mockFooBaz.getValue).thenReturn(new Baz());

    Foo<Qux> mockFooQux = mockFoo();
    when(mockFooQux.getValue).thenReturn(new Qux());
    // ...
}

@SuppressWarnings("unchecked") // still needed :( but just once :)
private <T> Foo<T> mockFoo() {
    return mock(Foo.class);
}

19voto

Tobias Uhmann Punkte 2267

Ich stimme zu, dass man Warnungen in Klassen oder Methoden nicht unterdrücken sollte, da man andere, versehentlich unterdrückte Warnungen übersehen könnte. Aber IMHO ist es absolut vernünftig, eine Warnung zu unterdrücken, die nur eine einzige Codezeile betrifft.

@SuppressWarnings("unchecked")
Foo<Bar> mockFoo = mock(Foo.class);

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