Domanda

Esiste un metodo pulito per deridere una classe con parametri generici? Supponiamo di dover deridere una classe Foo<T> che devo passare a un metodo che prevede un Foo<Bar>. Posso fare quanto segue abbastanza facilmente:

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

Supponendo che getValue() restituisca il tipo generico T. Ma questo avrà gattini quando in seguito lo passerò a un metodo in attesa di <=>. Il casting è l'unico mezzo per farlo?

È stato utile?

Soluzione

Penso che tu debba lanciarlo, ma non dovrebbe essere così male:

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

Altri suggerimenti

Un altro modo per aggirare questo è usare invece @Mock annotazione. Non funziona in tutti i casi, ma sembra molto più sexy :)

Ecco un esempio:

@RunWith(MockitoJUnitRunner.class)
public class FooTests {

    @Mock
    public Foo<Bar> fooMock;

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

Il MockitoJUnitRunner inizializza i campi annotati con <=> .

Puoi sempre creare una classe / interfaccia intermedia in grado di soddisfare il tipo generico che desideri specificare. Ad esempio, se Foo fosse un'interfaccia, potresti creare la seguente interfaccia nella tua classe di test.

private interface FooBar extends Foo<Bar>
{
}

In situazioni in cui Foo è una classe non finale , puoi semplicemente estendere la classe con il seguente codice e fare la stessa cosa:

public class FooBar extends Foo<Bar>
{
}

Quindi puoi utilizzare uno degli esempi sopra con il seguente codice:

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

Crea un metodo dell'utilità di test . Utile specialmente se ne hai bisogno per più di una volta.

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

Ecco un caso interessante: il metodo riceve una raccolta generica e restituisce una raccolta generica dello stesso tipo di base. Ad esempio:

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

Questo metodo può essere deriso con la combinazione di Mockito anyCollectionOf matcher e la risposta.

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

Concordo sul fatto che non si dovrebbero sopprimere gli avvisi in classi o metodi in quanto si potrebbero trascurare gli altri avvisi soppressi accidentalmente. Ma IMHO è assolutamente ragionevole sopprimere un avviso che riguarda solo una singola riga di codice.

@SuppressWarnings("unchecked")
Foo<Bar> mockFoo = mock(Foo.class);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top