Sou novato no desenvolvimento e nos testes de unidade em particular. Eu acho que meu requisito é bastante simples, mas estou interessado em saber o que os outros pensam sobre isso.
Suponha que eu tenha duas classes assim -
public class First {
Second second ;
public First(){
second = new Second();
}
public String doSecond(){
return second.doSecond();
}
}
class Second {
public String doSecond(){
return "Do Something";
}
}
Digamos que estou escrevendo teste de unidade para testar o First.doSecond()
método. No entanto, suponha, eu quero a Second.doSecond()
classe Mock assim. Estou usando o Mockito para fazer isso.
public void testFirst(){
Second sec = mock(Second.class);
when(sec.doSecond()).thenReturn("Stubbed Second");
First first = new First();
assertEquals("Stubbed Second", first.doSecond());
}
Estou vendo que a zombaria não entra em vigor e a afirmação falha. Não há como zombar das variáveis de membro de uma classe que eu quero testar. ?
Isso não é possível se você não puder alterar seu código. Mas eu gosto de injeção de dependência e o Mockito suporta:
Seu teste:
Isso é muito agradável e fácil.
fonte
Se você olhar atentamente para o seu código, verá que a
second
propriedade em seu teste ainda é uma instânciaSecond
, não uma simulação (você não passa a simulaçãofirst
no seu código).A maneira mais simples seria criar um setter para
second
aFirst
classe e passá-lo o mock explicitamente.Como isso:
Outra seria passar uma
Second
instância comoFirst
parâmetro construtor.Se você não pode modificar o código, acho que a única opção seria usar a reflexão:
Mas você provavelmente pode, pois é raro fazer testes no código que você não controla (embora se possa imaginar um cenário em que você precise testar uma biblioteca externa porque o autor não fez :))
fonte
@Mock
e anote primeiro com@InjectMocks
e instancia primeiro no inicializador. O Mockito fará automaticamente o melhor para encontrar um local para injetar o segundo mock na primeira instância, incluindo a configuração de campos particulares que correspondem ao tipo.@Mock
foi em torno de 1,5 (talvez mais cedo, não tenho certeza). 1.8.3 introduzido@InjectMocks
, bem como@Spy
e@Captor
.Se você não pode alterar a variável de membro, o contrário é usar o powerMockit e chamar
Agora, o problema é que QUALQUER chamada para o novo Second retornará a mesma instância simulada. Mas no seu caso simples, isso funcionará.
fonte
Eu tive o mesmo problema em que um valor privado não foi definido porque o Mockito não chama super construtores. Aqui está como eu aumento a zombaria com a reflexão.
Primeiro, criei uma classe TestUtils que contém muitos utilitários úteis, incluindo esses métodos de reflexão. O acesso à reflexão é um pouco complicado de implementar a cada vez. Criei esses métodos para testar o código em projetos que, por um motivo ou outro, não tinham pacote de simulação e não fui convidado a incluí-lo.
Então eu posso testar a classe com uma variável privada como esta. Isso é útil para zombar das árvores de classe que você não tem controle também.
Modifiquei meu código do meu projeto atual aqui, na página. Pode haver um problema de compilação ou dois. Eu acho que você entendeu a ideia geral. Sinta-se livre para pegar o código e usá-lo, se achar útil.
fonte
Muitas pessoas já o aconselharam a repensar seu código para torná-lo mais testável - bons conselhos e geralmente mais simples do que o que estou prestes a sugerir.
Se você não pode alterar o código para torná-lo mais testável, PowerMock: https://code.google.com/p/powermock/
O PowerMock estende o Mockito (para que você não precise aprender uma nova estrutura simulada), fornecendo funcionalidade adicional. Isso inclui a capacidade de um construtor retornar um mock. Poderoso, mas um pouco complicado - portanto, use-o criteriosamente.
Você usa um corredor de simulação diferente. E você precisa preparar a classe que irá invocar o construtor. (Observe que essa é uma pegadinha comum - prepare a classe que chama o construtor, não a classe construída)
Em sua configuração de teste, você pode usar o método whenNew para que o construtor retorne uma simulação
fonte
Sim, isso pode ser feito, como mostra o seguinte teste (escrito com a API de simulação do JMockit, que eu desenvolvo):
Com o Mockito, no entanto, esse teste não pode ser gravado. Isso ocorre devido à maneira como o mocking é implementado no Mockito, onde é criada uma subclasse da classe a ser mocked; somente instâncias dessa subclasse "mock" podem ter comportamento simulado, portanto, é necessário que o código testado as use em vez de qualquer outra instância.
fonte
Se você deseja uma alternativa ao ReflectionTestUtils da Spring no mockito, use
fonte