Como um contêiner IoC pode ser usado para testes de unidade? É útil gerenciar mocks em uma solução enorme (mais de 50 projetos) usando IoC? Alguma experiência? Alguma biblioteca C # que funciona bem para usá-lo em testes de unidade?
Como um contêiner IoC pode ser usado para testes de unidade? É útil gerenciar mocks em uma solução enorme (mais de 50 projetos) usando IoC? Alguma experiência? Alguma biblioteca C # que funciona bem para usá-lo em testes de unidade?
Respostas:
De modo geral, um DI Container não deve ser necessário para o teste de unidade porque o teste de unidade trata da separação de responsabilidades.
Considere uma classe que usa injeção de construtor
public MyClass(IMyDependency dep) { }
Em todo o seu aplicativo, pode ser que haja um enorme gráfico de dependência oculto por trás IMyDependency
, mas em um teste de unidade, você reduz tudo para um único Teste Duplo .
Você pode usar simulações dinâmicas como Moq ou RhinoMocks para gerar o Test Double, mas não é necessário.
var dep = new Mock<IMyDependency>().Object;
var sut = new MyClass(dep);
Em alguns casos, pode ser bom ter um contêiner de simulação automática , mas você não precisa usar o mesmo contêiner DI que o aplicativo de produção usa.
Como um contêiner Ioc pode ser usado para testes de unidade?
IoC irá impor paradigmas de programação que tornarão o teste de unidade isoladamente (ou seja, usando simulações) mais fácil: uso de interfaces, sem new (), sem singletons ...
Mas usar o contêiner IoC para teste não é realmente um requisito, ele apenas fornecerá alguns recursos, por exemplo, injeção de simulações, mas você pode fazer isso manualmente.
É útil gerenciar mocks em uma solução enorme (mais de 50 projetos) usando IoC?
Não tenho certeza do que você quer dizer com gerenciamento de simulações usando IoC. De qualquer forma, os contêineres IoC geralmente podem fazer mais do que apenas injetar simulações quando se trata de testes. E se você tiver um suporte IDE decente que torne a refatoração possível, por que não usá-lo?
Alguma experiência?
Sim, em uma solução enorme, você precisa mais do que nunca de uma solução não sujeita a erros e adversa à refatoração (ou seja, por meio de um contêiner IoC seguro de tipo ou bom suporte IDE).
Costumo usar um contêiner IoC em meus testes. É verdade que eles não são "testes de unidade" no sentido puro. IMO Eles são mais BDDish e facilitam a refatoração. Os testes existem para lhe dar confiança para refatorar. Testes mal escritos podem ser como colocar cimento em seu código.
Considere o seguinte:
[TestFixture]
public class ImageGalleryFixture : ContainerWiredFixture
{
[Test]
public void Should_save_image()
{
container.ConfigureMockFor<IFileRepository>()
.Setup(r => r.Create(It.IsAny<IFile>()))
.Verifiable();
AddToGallery(new RequestWithRealFile());
container.VerifyMockFor<IFileRepository>();
}
private void AddToGallery(AddBusinessImage request)
{
container.Resolve<BusinessPublisher>().Consume(request);
}
}
Várias coisas acontecem ao adicionar uma imagem à galeria. A imagem é redimensionada, uma miniatura é gerada e os arquivos são armazenados no AmazonS3. Usando um contêiner, posso isolar mais facilmente apenas o comportamento que desejo testar, que, neste caso, é a parte persistente.
Uma extensão de contêiner de simulação automática é útil ao usar esta técnica: http://www.agileatwork.com/auto-mocking-unity-container-extension/
Usando contêineres com capacidade para resolver serviços não registrados / desconhecidos como SimpleInjector , DryIoc (seu meu) pode retornar simulações para interfaces ainda não implementadas.
O que significa que você pode iniciar o desenvolvimento com a primeira implementação simples e suas dependências simuladas e substituí-las por coisas reais conforme você avança.