Eu escrevi uma fábrica para produzir java.sql.Connection
objetos:
public class MySQLDatabaseConnectionFactory implements DatabaseConnectionFactory {
@Override public Connection getConnection() {
try {
return DriverManager.getConnection(...);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
Gostaria de validar os parâmetros passados DriverManager.getConnection
, mas não sei como zombar de um método estático. Estou usando o JUnit 4 e o Mockito para meus casos de teste. Existe uma boa maneira de simular / verificar esse caso de uso específico?
java
unit-testing
mocking
mockito
Naftuli Kay
fonte
fonte
static
métodos de simulação , mas por acidente . Essa limitação (junto com o suporte afinal
classes / métodos de simulação ounew
objetos com ou sem simulação ) é uma consequência natural (mas não intencional) da abordagem empregada para implementar a simulação, onde são criadas dinamicamente novas classes que implementam / estendem o tipo a ser ridicularizado; outras bibliotecas de simulação usam outras abordagens que evitam essas limitações. Isso aconteceu no mundo .NET também.Respostas:
Use o PowerMockito em cima do Mockito.
Código de exemplo:
Mais Informações:
fonte
@RunWith(PowerMockRunner.class)
isso abaixo@PowerMockRunnerDelegate(JUnit4.class)
.A estratégia típica para evitar métodos estáticos que você não tem como evitar, é criar objetos quebrados e, em vez disso, usar os objetos quebrados.
Os objetos do wrapper se tornam fachadas para as classes estáticas reais e você não as testa.
Um objeto wrapper pode ser algo como
Finalmente, sua classe em teste pode usar esse objeto singleton, por exemplo, tendo um construtor padrão para uso na vida real:
E aqui você tem uma classe que pode ser facilmente testada, porque você não usa diretamente uma classe com métodos estáticos.
Se você estiver usando o CDI e puder fazer uso da anotação @Inject, será ainda mais fácil. Basta fazer o seu bean Wrapper @ApplicationScoped, injetar essa coisa como colaborador (você nem precisa de construtores confusos para teste) e continuar com a zombaria.
fonte
Eu tive uma questão semelhante. A resposta aceita não funcionou para mim, até que eu fiz a alteração :, de
@PrepareForTest(TheClassThatContainsStaticMethod.class)
acordo com a documentação do mockMatic do PowerMock .E eu não preciso usar
BDDMockito
.Minha classe:
Minha classe de teste:
fonte
Como mencionado anteriormente, você não pode zombar de métodos estáticos com o mockito.
Se alterar sua estrutura de teste não for uma opção, faça o seguinte:
Crie uma interface para o DriverManager, zombe dessa interface, injete-a através de algum tipo de injeção de dependência e verifique nessa zombaria.
fonte
Observação: quando você chama o método estático dentro de uma entidade estática, precisa alterar a classe em @PrepareForTest.
Por exemplo:
Para o código acima, se você precisar zombar da classe MessageDigest, use
Enquanto se você tem algo como abaixo:
então, você precisará preparar a classe em que esse código reside.
E depois zombe do método:
fonte
Você pode fazer isso com um pouco de refatoração:
Em seguida, você pode estender sua classe
MySQLDatabaseConnectionFactory
para retornar uma conexão falsa, fazer afirmações sobre os parâmetros etc.A classe estendida pode residir no caso de teste, se estiver localizado no mesmo pacote (o que eu encorajo você a fazer)
fonte
Para zombar do método estático, você deve usar o Powermock: https://github.com/powermock/powermock/wiki/MockStatic . Mockito não fornece essa funcionalidade.
Você pode ler um bom artigo sobre mockito: http://refcardz.dzone.com/refcardz/mockito
fonte
O Mockito não pode capturar métodos estáticos, mas desde o Mockito 2.14.0 você pode simulá-lo criando instâncias de chamada de métodos estáticos.
Exemplo (extraído de seus testes ):
Seu objetivo não é oferecer suporte direto à zombaria estática, mas melhorar suas APIs públicas, para que outras bibliotecas, como o Powermockito , não precisem depender de APIs internas ou duplicar diretamente algum código Mockito. ( fonte )
fonte
Também escrevi uma combinação de Mockito e AspectJ: https://github.com/iirekm/varia/tree/develop/ajmock
Seu exemplo se torna:
fonte
Como esse método é estático, ele já possui tudo o que você precisa para usá-lo e, portanto, anula o propósito da zombaria. Zombar dos métodos estáticos é considerado uma má prática.
Se você tentar fazer isso, significa que há algo errado com a maneira como você deseja executar os testes.
Claro que você pode usar o PowerMockito ou qualquer outra estrutura capaz de fazer isso, mas tente repensar sua abordagem.
Por exemplo: tente simular / fornecer os objetos que esse método estático consome.
fonte
Use a estrutura JMockit . Funcionou para mim. Você não precisa escrever instruções para zombar do método DBConenction.getConnection (). Apenas o código abaixo é suficiente.
@Mock abaixo é mockit.Mock package
fonte