Question

Existe-t-il une méthode propre pour se moquer d'une classe avec des paramètres génériques? Disons que je dois me moquer d'une classe Foo<T> que je dois passer à une méthode qui attend un Foo<Bar>. Je peux faire assez facilement les choses suivantes:

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

En supposant que getValue() renvoie le type générique T. Mais cela va avoir des chatons quand je le passerai plus tard dans une méthode en attente de <=>. Est-ce que le casting est le seul moyen de le faire?

Était-ce utile?

La solution

Je pense que vous avez besoin de le lancer, mais ça ne devrait pas être trop grave:

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

Autres conseils

Une autre solution consiste à utiliser @Mock une annotation à la place. Ne fonctionne pas dans tous les cas, mais semble beaucoup plus sexy:)

Voici un exemple:

@RunWith(MockitoJUnitRunner.class)
public class FooTests {

    @Mock
    public Foo<Bar> fooMock;

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

Le MockitoJUnitRunner initialise les champs annotés avec <=> .

Vous pouvez toujours créer une classe / interface intermédiaire répondant au type générique que vous souhaitez spécifier. Par exemple, si Foo était une interface, vous pouvez créer l’interface suivante dans votre classe de test.

private interface FooBar extends Foo<Bar>
{
}

Dans les cas où Foo est une classe non finale , vous pouvez simplement étendre la classe avec le code suivant et faire la même chose:

public class FooBar extends Foo<Bar>
{
}

Ensuite, vous pouvez utiliser l'un des exemples ci-dessus avec le code suivant:

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

Créez une méthode d'utilitaire de test . Spécialement utile si vous en avez besoin plus d'une fois.

@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);
}

Voici un cas intéressant: la méthode reçoit une collection générique et retourne une collection générique du même type de base. Par exemple:

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

Cette méthode peut être simulée avec la combinaison du matcher Mockito anyCollectionOf et de la réponse.

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

Je conviens qu'il ne faut pas supprimer les avertissements dans les classes ou les méthodes, car on pourrait négliger d'autres avertissements supprimés accidentellement. Mais à mon humble avis, il est absolument raisonnable de supprimer un avertissement qui n’affecte qu’une seule ligne de code.

@SuppressWarnings("unchecked")
Foo<Bar> mockFoo = mock(Foo.class);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top