Eu tenho um arquivo de recurso que tem algumas configurações. Eu tenho uma classe ResourceLoader que carrega as configurações deste arquivo. Atualmente, esta classe é uma classe singleton instanciada ansiosamente. Assim que essa classe é carregada, ela lê as configurações do arquivo (caminho do arquivo armazenado como um campo constante em outra classe). Algumas dessas configurações não são adequadas para testes de unidade. Por exemplo, eu tenho um tempo de suspensão do encadeamento neste arquivo, que pode levar horas para o código de produção, mas eu gostaria que fosse alguns milissegundos para testes de unidade. Então, eu tenho outro arquivo de recurso de teste que tem um conjunto diferente de valores. Minha pergunta é como faço para trocar o arquivo principal de recursos por esse arquivo de teste durante o teste de unidade? O projeto é um projeto inteligente e estou usando o testng como estrutura de teste. Estas são algumas das abordagens que eu
Use @BeforeSuite e modifique a variável constante FilePath para apontar para o arquivo de teste e use @AfterSuite para apontar de volta para o arquivo original. Isso parece estar funcionando, mas acho que porque a classe ResourceLoader é instantaneamente instanciada, não há garantia de que o método @BeforeSuite sempre seja executado antes do carregamento da classe ResourceLoader e, portanto, propriedades antigas podem ser carregadas antes que o caminho do arquivo seja alterado. Embora a maioria dos compiladores carregue uma classe somente quando necessário, não tenho certeza se esse é um requisito de especificação java. Portanto, em teoria, isso pode não funcionar para todos os compiladores java.
Passe o caminho do arquivo de recursos como um argumento de linha de comando. Posso adicionar o caminho do arquivo de recurso de teste como argumento da linha de comando na configuração infalível no pom. Isso parece um pouco excessivo.
Use a abordagem em 1. e torne o ResourceLoader preguiçoso instanciado. Isso garante que se @BeforeMethod for chamado antes da primeira chamada para ResourceLoader.getInstance (). GetProperty (..), o ResourceLoader carregará o arquivo correto. Isso parece ser melhor do que as duas primeiras abordagens, mas acho que tornar uma classe singleton preguiçosa instancia torna-a feia, pois não posso usar um padrão simples como torná-la uma enumeração e tal (como é o caso da instanciação ansiosa).
Parece um cenário comum, qual é a maneira mais comum de fazer isso?
fonte
Respostas:
Todos os singletons quer ansiosamente ou preguiçosamente instanciado são anti-padrão . O uso de singletons torna o teste de unidade mais difícil, porque não há uma maneira fácil de zombar de singleton.
Método estático simulado
Uma solução alternativa é usar o PowerMock para simular o método estático que retorna a instância singleton.
Use injeção de dependência
Uma solução melhor é usar a injeção de dependência. Se você já usa uma estrutura de injeção de dependência (por exemplo, Spring, CDI), refatorar o código para criar
ResourceLoader
um bean gerenciado com escopo singleton .Se você não usar uma estrutura de injeção de dependência, uma refatoração fácil será fazer alterações em todas as classes usando o singleton
ResourceLoader
:E então em testes unitários simulados
ResourceLoader
usando MockitoExternalizar configuração
Outra abordagem é colocar um arquivo com configurações de teste em
src/test/resources
. Se você armazenar as configurações nosrc/main/resources/application.properties
, um arquivosrc/test/resources/application.properties
o substituirá.Além disso, externalizar a configuração para um arquivo não compactado em um JAR é uma boa idéia. Dessa forma, o arquivo
src/main/resources/application.properties
conterá propriedades padrão e um arquivo passado usando o parâmetro de linha de comando substituirá essas propriedades. Portanto, um arquivo com propriedades de teste também será passado como parâmetro de linha de comando. Veja como o Spring lida com a configuração externalizada .Usar propriedades do sistema Java
Uma abordagem ainda mais fácil é permitir a substituição de propriedades padrão pelas Propriedades do sistema no método
ResourceLoader.getInstance().getProperty()
e passar as propriedades de teste dessa maneirafonte
Verifique se você está no jUnit
Você também pode verificar em tempo de execução se o jUnit está em execução e depois trocar o caminho. Isso funcionaria assim ( não testado ):
fonte