Pergunta

Existe um método limpo de zombar uma classe com parâmetros genéricos? Digamos que eu tenha para zombar um Foo<T> classe que eu preciso passar para um método que espera um Foo<Bar>. I pode fazer o seguinte com bastante facilidade:

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

Assumindo getValue() retorna o tipo T genérico. Mas isso vai ter gatinhos quando eu depois passá-lo em um método esperando Foo<Bar>. Está lançando o único meio de fazer isso?

Foi útil?

Solução

Eu acho que você precisa fazer para lançá-lo, mas não deve ser muito ruim:

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

Outras dicas

Uma outra maneira de contornar isso é usar anotação @Mock vez. Não funciona em todos os casos, mas parece muito mais sexy:)

Aqui está um exemplo:

@RunWith(MockitoJUnitRunner.class)
public class FooTests {

    @Mock
    public Foo<Bar> fooMock;

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

O MockitoJUnitRunner inicializa os campos anotado com @Mock .

Você pode sempre criar uma classe / interface de intermediário que iria satisfazer o tipo genérico que você está querendo especificar. Por exemplo, se Foo era uma interface, você pode criar a seguinte interface em sua classe de teste.

private interface FooBar extends Foo<Bar>
{
}

Em situações onde Foo é um não-final classe, você poderia simplesmente estender a classe com o seguinte código e fazer a mesma coisa:

public class FooBar extends Foo<Bar>
{
}

Em seguida, você poderia consumir qualquer um dos exemplos acima com o seguinte código:

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

Criar um método de utilitário de teste . Especialmente útil se você precisar dele para mais de uma vez.

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

Aqui é um caso interessante: método receieves coleção genérica e retorna coleção genérica do mesmo tipo base. Por exemplo:

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

Este método pode ser escarnecido com a combinação de Mockito anyCollectionOf correspondência e a resposta.

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

Eu concordo que não se deve avisos suprimir em classes ou métodos como se poderia ignorar outras, os avisos acidentalmente suprimidas. Mas IMHO é absolutamente razoável para suprimir um aviso que afeta apenas uma única linha de código.

@SuppressWarnings("unchecked")
Foo<Bar> mockFoo = mock(Foo.class);
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top