Pergunta

Estou tentando aprender injeção de dependência e encontrei um problema ao testar o aplicativo.

Estou escrevendo um aplicativo de console e o contêiner é criado e inicializado em main (), está disponível como um get-property dentro Program.Container, então em qualquer lugar do meu aplicativo que eu possa ligar Program.Container.Resolve<..>().

Eu tenho uma aula do ServiceValidator como esta:

public class ServiceValidator
{
    private readonly IConfiguration _configuration;
    private readonly IService _service;

    public ServiceValidator(IConfiguration configuration, IService service)
    {
        _configuration = configuration;
        _service = service;
    }

Em outra aula que eu uso

ServiceValidator serviceValidator = Program.Container.Resolve<ServiceValidator>();
serviceValidator.VerifyVersion();

É o chamado para Program.Container.Resolve Isso me causa problemas no teste de unidade, pois não foi configurado.

Isso é uma prática ruim, para chamar a resolução no contêiner? Eu poderia criar a instância do ServiceValidator em Main() E passe o objeto, mas isso parece estúpido, pois causaria muitos parâmetros para os objetos que acabaram de passar para o próximo método.

Então, acho que é aceitável chamar a resolução dentro de uma classe, mas o contêiner deve ser configurado para o teste de unidade. Como devo fazer isso, devo mover o contêiner para outro lugar além da classe do programa? O que você recomendaria?

Se isso importa, estou usando o Unity e o C#

Obrigado :-)

Foi útil?

Solução

Isso é uma prática ruim, para chamar a resolução no contêiner? Eu poderia criar a instância do ServiceValidator em Main () e passar o objeto, mas isso parece estúpido, pois causaria muitos parâmetros para os objetos que acabaram de passar para o próximo método.

Quando você usa a injeção de dependência, não precisará passar muitos parâmetros para objetos. O construtor de cada objeto deve ter como parâmetros apenas as dependências que ele próprio usa diretamente - ele não saberá sobre as dependências transitivas de suas dependências diretas.

Portanto, se você possui uma classe X que exige um ServiceValidator, a classe X terá um parâmetro construtor do Type ServiceValidator. Então, se alguns Classe Y usarem classe X, então a classe Y terá um parâmetro construtor do tipo X. Observe que Y não sabe nada Sobre o ServiceValidator, para que você não precise passar pelo ServiceValidator de uma classe para outra - o único lugar onde é usado é quando a construção de X, e isso é frequentemente feito por uma estrutura DI ou em apenas um lugar em um lugar escrito à mão fábrica.

Alguns links para mais informações:

Outras dicas

Normalmente, permito que as chamadas resolvam dependências do contêiner em lugares como o principal, embora ainda tente mantê -las no mínimo. O que eu faço então é configurar o contêiner em um método de inicialização de uma classe de teste. Eu o inicializei com implementações falsas para qualquer classe de teste que precise chamar o contêiner.

As classes de teste que não chamam nada de exigir que o contêiner sejam inicializadas podem ignorá -lo e não usar as falsificações. Eu geralmente uso zombarias nessas instâncias.

Eu também uso o Microsoft Service Locator para que a dependência que estou tomando é de algo da estrutura .NET em vez de em um contêiner específico. Isso me permite que eu use o que eu quiser até mesmo um recipiente fabricado em casa.

Você pode usar uma classe estática como inicializador para o seu contêiner. Algo como o bootstrapper.cs seria bom. Você pode fazer referência aos métodos de classe tanto em seu código quanto em testes.

Bem, o que você está fazendo tecnicamente é um local de serviço em sua classe.

Lembro -me de ler este artigo há um tempo:

http://martinfowler.com/articles/injection.html

Nas minhas aulas, nunca tento usar a resolução nelas. Eu crio os objetos através do contêiner quando preciso deles. Para testes de unidade, uso algumas classes de biblioteca e stub simuladas.

O problema está no fato de você estar tentando testar o método principal. Este método é praticamente impossível de unidade de teste.

Eu argumentaria que é melhor não testar seu método principal porque:

  • A ênfase dos testes modernos de unidade é sobre design
  • Você deve minimizar a dependência da configuração nos testes de unidade. A configuração pode ser testada com testes de fumaça ou integração.
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top