Eu escrevi alguns testes de unidade para um método estático. O método estático usa apenas um argumento. O tipo do argumento é uma classe final. Em termos de código:
public class Utility {
public static Optional<String> getName(Customer customer) {
// method's body.
}
}
public final class Customer {
// class definition
}
Então, para a Utility
classe, criei uma classe de teste UtilityTests
na qual escrevi testes para esse método getName
,. A estrutura de teste de unidade é TestNG e a biblioteca de zombaria usada é Mockito
. Portanto, um teste típico tem a seguinte estrutura:
public class UtilityTests {
@Test
public void getNameTest() {
// Arrange
Customer customerMock = Mockito.mock(Customer.class);
Mockito.when(...).thenReturn(...);
// Act
Optional<String> name = Utility.getName(customerMock);
// Assert
Assert.assertTrue(...);
}
}
Qual é o problema ?
Enquanto os testes são executados com sucesso localmente, dentro do IntelliJ, eles falham no Jenkins (quando pressiono meu código na ramificação remota, uma compilação é acionada e os testes de unidade são executados no final). A mensagem de erro é sth como o seguinte:
org.mockito.exceptions.base.MockitoException: Não é possível zombar / espionar a classe com.packagename.Customer O Mockito não pode zombar / espionar porque: - classe final
O que eu tentei?
Eu procurei um pouco, a fim de encontrar uma solução, mas não consegui. Eu notar aqui que estou não permitido mudar o fato de que Customer
é uma última classe. Além disso, eu gostaria, se possível, de não mudar seu design (por exemplo, criar uma interface que contenha os métodos que eu quero zombar e afirmar que a classe Customer implementa essa interface, como Jose corretamente apontou em seu Comente). O que eu tentei é a segunda opção mencionada no mockito-final . Apesar de ter resolvido o problema, ele travou alguns outros testes de unidade :(, que não podem ser corrigidos de maneira aparente.
Questões
Então, aqui estão as duas perguntas que tenho:
- Como isso é possível em primeiro lugar? O teste não deveria falhar localmente e em Jenkins?
- Como isso pode ser corrigido com base nas restrições mencionadas acima?
Agradecemos antecipadamente por qualquer ajuda.
fonte
enable final
configuração funcione no seu espaço de trabalho, mas quando executadaJenkins
não consegue encontrar esse arquivo. Verifique ondeJenkins
está procurando o arquivo e se ele está realmente lá ou não.Customer
alguma lógica ou é apenas uma classe de dados idiota? Se for apenas um monte de campos com getters e setters, você poderá instanciar.Respostas:
Uma abordagem alternativa seria usar o padrão 'método para classificar'.
Aqui está um bom blog sobre o tema: https://simpleprogrammer.com/back-to-basics-mock-eliminating-patterns/
fonte
Obviamente, é uma espécie de ambiente específico. A única questão é - como determinar a causa da diferença.
Eu sugiro que você verifique o
org.mockito.internal.util.MockUtil#typeMockabilityOf
método e compare, o quemockMaker
é realmente usado nos dois ambientes e por quê.Se
mockMaker
for o mesmo - compare as classes carregadasIDE-Client
vsJenkins-Client
- elas têm alguma diferença no tempo de execução do teste.O código a seguir foi escrito assumindo o OpenJDK 12 e o Mockito 2.28.2, mas acredito que você pode ajustá-lo para qualquer versão realmente usada.
Com uma regra separada para zombarias em linha:
fonte
Certifique-se de executar o teste com os mesmos argumentos. Verifique se suas configurações de execução intellij correspondem aos jenkins. https://www.jetbrains.com/help/idea/creating-and-editing-run-debug-configurations.html . Você pode tentar executar o teste na máquina local com os mesmos argumentos que no jenkins (do terminal), se falhar, isso significa que o problema está nos argumentos
fonte
org.mockito.plugins.MockMaker
também existe na máquina jenkins. Eu uso a mesma JVM em máquinas de bot. Vou verificar os 3 que você apontou. Obrigado