A injeção de dependência é essencial para o teste de unidade?

48

Está usando injeção de dependência (DI) essencial para testes unitários?

Não consigo pensar em outra alternativa para isolar o código, para que possa ser testado. Além disso, todos os exemplos que já vi usam esse padrão. É porque é a única opção viável ou existem outras alternativas?

    
por Tom Squires 22.03.2012 / 16:34
fonte

7 respostas

36

DI torna o teste de unidade muito mais fácil. Mas você ainda pode escrever testes de unidade sem DI. Muitos testes de unidade já foram escritos antes que a DI se generalizasse. (É claro que algumas dessas técnicas usadas são idênticas ou muito parecidas com DI, sem saber que tem um nome chique: -)

Eu mesmo usei, e. interfaces e fábricas muito antes de aprender sobre DI. O nome da classe de fábrica real pode ter sido lido de um arquivo de configuração ou passado para o SUT como um argumento.

Outra abordagem é usar singletons (ou dados globalmente acessíveis em geral). Sim, eu sei que não é recomendado por muitos (inclusive eu) em geral. Ainda assim, pode ser viável em situações específicas, especialmente se o singleton contiver dados de configuração estática que não sejam específicos do caso de teste, mas que difiram entre a produção e o ambiente de teste. Claro que tem seus problemas conhecidos, então DI é superior se você puder usá-lo. Mas muitas vezes (por exemplo, em sistemas legados) você não pode.

Falando nisso, Trabalhando efetivamente com o código legado descreve vários truques para obter o código legado coberto pelos testes . Muitos deles não são bons e não são uma solução a longo prazo. Mas eles permitem que você crie os primeiros testes unitários valiosos para um sistema que, de outra forma, não seria testado ... o que permite que você inicie a refatoração e eventualmente (entre outros) introduza o DI.

    
por 22.03.2012 / 16:37
fonte
51

O desacoplamento é essencial para testes unitários. DI é uma ótima maneira de conseguir o desacoplamento.

    
por 22.03.2012 / 17:22
fonte
9

Dependendo das tecnologias que você está usando, você pode isolar dependências sem usar DI. Por exemplo, no mundo do .NET, as Moles permitem que você isole as dependências sem o padrão DI. / p>

Dito isso, acredito que essas estruturas de isolamento sejam escritas e destinadas a situações em seu código com dependências externas (sistema de arquivos, banco de dados, etc.). Isto é, o fato de alguém poder fazer isso não significa que ele ou ela deveria.

Injeção de dependência permite testes unitários, mas também permite modificar o comportamento de um objeto sem alterar o código daquele objeto (princípio aberto / fechado). Portanto, não é apenas um código testável, mas um código flexível resultante. Eu geralmente descobri que há uma strong correlação entre código flexível / mantenível / código testável.

    
por 22.03.2012 / 16:38
fonte
4

Não, DI não é essencial para testes unitários, mas ajuda muito.

Você pode usar fábricas ou localizadores e testar como faria com DI (não tão elegante e exigiria mais configuração).

Além disso, os Objetos Mock seriam importantes em sistemas legados, onde muitas chamadas são delegadas a funções em vez de dependências. (Mock Objects também pode ser extensivamente utilizado em uma configuração adequada)

Pode haver configurações em que o teste é quase impossível. Mas isso não é baseado em se a injeção de dependência é usada ou não.

    
por 22.03.2012 / 17:23
fonte
2

Não , a injeção de dependência não é essencial para o teste de unidade.

A injeção de dependência ajuda se você tiver uma classe que precise de uma instância de classe dependente para fazer algum subprocesso. Em vez de DI, você pode separar a lógica de um método de negócio em uma parte de coleta de dados (que não é testável em unidade) e uma parte de cálculo que pode ser testada por unidade.

Exemplo (usando DI) Esta implementação depende de Employee, Account, ....

 bool hasPermissionToTranferMony(Employee employee, Account from, Account to, Money amount)
 {
     if (amount > 100 && imployee.isStudent())
        return false;
     if (to.getOwner().getFamiliyName() == Employee.getFamiliyName() && ...
        return false; // cannot transfer money to himself;
     ...
 }

Após a separação de dados e cálculo

 bool hasPermissionToTranferMony(Employee employee, Account from, Account to, Money amount)
 {
     return hasPermissionToTranferMony(employee.isStudent(), Employee.getFamiliyName(),  to.getOwner().getFamiliyName(), ....);
 }

 // the actualal permission calculation
 static bool hasPermissionToTranferMony(boolean isStudent, string employeeFamiliyName, string receiverFamiliyName, .....)
     if (amount > 100 && isStudent)
        return false;
     if (receiverFamiliyName == employeeFamiliyName && ...
        return false; // cannot transfer money to himself;
     ...
 }

A parte de cálculo pode ser facilmente testada sem injeção de dependência.

    
por 04.05.2012 / 11:23
fonte
1
  • Injeção de dependência não é essencial para testes unitários

  • Inversão de controle, por outro lado, é essencial quando você deseja trocar uma implementação por outra.

por 04.05.2012 / 11:41
fonte
0

Sim, existem alternativas ao uso de DI para isolamento.

Uma alternativa é usar fábricas ou um ServiceLocator que pode ser configurado a partir de testes para retornar objetos simulados em vez dos reais.

Outra é usar uma estrutura de isolamento adequada ou ferramenta de zombaria. Tais ferramentas existem para praticamente todas as linguagens modernas de programação (para Java, C #, Ruby e Python, pelo menos). Eles podem isolar uma classe que está sendo testada a partir da implementação de outras classes / tipos, mesmo quando a classe testada instancia diretamente suas dependências.

    
por 31.01.2014 / 21:32
fonte