Como escrever testes de integração e sistema no ASP.NET MVC
-
26-09-2019 - |
Pergunta
Minha aplicação
Eu tenho um design de aplicativo que se parece com o seguinte:
- Camada de aplicativos da Web - App ASP.NET MVC com controladores e visualizações que usam pocos e chamam serviços
- Camada de serviço - processos de negócios que usam pocos e repositórios de chamadas
- Camada de dados - repositórios que usam pocos e se comunicam com o modelo na forma do modelo EF, que faz parte dessa mesma camada
- Camada poco - define todas as classes usadas para inter -comunicação entre essas camadas
Portanto, minha camada de dados é completamente transparente à implementação do modelo de dados, porque a camada superior não usa entidades de dados.
Teste
Por mais que eu compreenda a unidade, a integração e o teste do sistema (com relação ao ASP.NET MVC) é o seguinte:
- Teste de unidade - este é fácil. Objetos desacoplados simulados e injetá -los em seu teste de unidade para que a unidade testada os use
- Teste de integração - deve fazer um grupo de unidades de funcionalidade de produção e zombar do resto: portanto, escrever testes de integração que testariam o controlador, o serviço e a integração do repositório sem realmente usar o banco de dados de produção
- Teste do sistema - Execute testes em todas as camadas sem zombaria, o que significa que tenho que usar o banco de dados de produção (teste)
Problema
Posso ver facilmente como escrever testes de unidade e testes do sistema, mas não sei como escrever testes de integração? Talvez minha visão disso esteja completamente distorcida e eu não os entendo.
Como se deve gravar testes de integração e sistema para um aplicativo ASP.NET MVC?
Ou qualquer aplicativo .NET para esse assunto?
Algum código que ajuda a explicar o problema
Suponha que eu tenha aulas como:
TaskController
chamadas paraTaskService
TaskService
chamadas paraTaskRepository
TaskRepository
manipular dados da EF internamente
Então, aqui estão minhas classes (abreviadas):
public class TaskController
{
private ITaskService service;
// injection constructor
public TaskController(ITaskService service)
{
this.service = service;
}
// default constructor
public TaskController() : this(new TaskService()) {}
public ActionResult GetTasks()
{
return View(this.service.GetTasks());
}
...
}
public class TaskService : ITaskService
{
private ITaskRepository repository;
// injection constructor
public TaskService(ITaskRepository repository)
{
this.repository = repository;
}
// default constructor
public TaskService() : this(new TaskRepository()) {}
public IList<Task> GetTasks()
{
return this.repository.GetTasks();
}
...
}
public class TaskRepository : ITaskRepository
{
public IList<Task> GetTasks()
{
// code that gets tasks from EF and converts to Task POCOs
}
...
}
O teste de unidade é simples e seria assim:
public void UnitTest()
{
var mock = new Mock<ITaskService>();
// other code that mocks the service
TaskController controller = new TaskController(mock.Object);
// do the test
}
Mas quando se trata de um teste de integração, como zombar de certas partes da integração.
public void IntegrationTest()
{
// no mocking at all
TaskController = new TaskController();
// do some testing
}
Primeiro de tudo, não posso simplesmente zombar do banco de dados aqui? Eu poderia zombar do repositório e ter serviço e controlador reais ...
Solução
Os testes de integração devem testar a integração entre os componentes. Enquanto os testes de unidade testam peças individuais de um único componente, a integração testa as interações entre os componentes e deve trabalhar ao vivo. Portanto, um teste de integração utilizaria um banco de dados e quaisquer outras dependências externas, onde é melhor zombar desses serviços nos testes de unidade.
O teste do sistema para mim seria o teste funcional (outro nível de teste usando algo como FIT) ou teste de interface do usuário através de uma ferramenta como o TestComplete ou a ferramenta de controle de qualidade da Telerik.
Hth.
Outras dicas
Testes de integração que não envolvem a interface do usuário ainda podem ser escritos em Nunit, Xunit, etc.
Para o ASP.NET MVC em particular (ou qualquer aplicativo da web), você pode usar Watin ou Selênio Para escrever testes de sistema/integração usando a interface do usuário.
Você também pode querer olhar para TST para testes de unidade T-SQL e SpecFlow Se você está curioso sobre o BDD no .NET.
Nota: Escrevi isso antes que a pergunta fosse atualizada com o código e uma descrição da situação específica. Realmente não aborda mais a questão, mas espero que ainda seja interessante/útil para alguém.
Acabei de responder a uma pergunta relacionada: Implementação de testes de integração. Eu acho que isso abordou a questão aqui, apresentando uma abordagem clara a ser adotada.
Parte da questão é que os testes de integração de nível superior ficam muito complexos v. Rapidamente. É a natureza do problema, por isso prefiro garantir que todas as peças separadas funcionem como pretendido, através de testes de unidade e testes de integração focados, dependendo da classe envolvida.
Com o acima no lugar, você só precisa garantir que as peças separadas sejam conectadas corretamente, por isso uso os testes completos do sistema para isso. Isso tem o melhor efeito se o código seguir sólido e seco.