Quero tornar uma classe testável usando injeção de dependência. Mas a classe cria vários objetos em tempo de execução e passa valores diferentes para o construtor. Aqui está um exemplo simplificado:
public abstract class Validator {
private ErrorList errors;
public abstract void validate();
public void addError(String text) {
errors.add(
new ValidationError(text));
}
public int getNumErrors() {
return errors.count()
}
}
public class AgeValidator extends Validator {
public void validate() {
addError("first name invalid");
addError("last name invalid");
}
}
(Existem muitas outras subclasses do Validator.)
Qual é a melhor maneira de mudar isso, para que eu possa injetar um objeto falso em vez de ValidationError?
Eu posso criar um AbstractValidationErrorFactory e injetar a fábrica. Isso funcionaria, mas parece que vou acabar criando toneladas de pequenas fábricas e interfaces de fábrica, para todas as dependências desse tipo. Existe uma maneira melhor?
Respostas:
A mudança mais simples para tornar sua unidade de classe testável é
Claro, isso não é muito bom. Mas permite que você cubra a classe com testes de unidade, após o qual você pode começar a refatorar para o design ideal, sem medo de quebrar o código com alterações mais profundas.
Referência obrigatória: trabalhando efetivamente com o código legado .
Sobre esse design ideal, é difícil dizer muito, pois seu exemplo carece de detalhes e contexto. Se você nos contar mais sobre o que você pretende testar e qual é o papel da classe testada, poderemos ajudar mais.
fonte
Normalmente, a solução para esse problema é o padrão do provedor:
Provedor é algo semelhante à fábrica. Nesse caso, ele retornará novo
ValidationError
sempre queget
for chamado.Mais informações podem ser encontradas no livro Injeção de Dependências na seção 3.3.2 (Reinjeção com o padrão Provedor).
Guice , por exemplo, tem um provedor para isso. Se você quiser algo mais sofisticado, use o AssistedInject .
fonte