Neste artigo vamos continuar a criar casos de testes para uma API Asp.Net Core usando xUnit. |
Continuando o artigo anterior vamos agora
criar casos de teste para testar o serviço.
Testando o Serviço
Vamos iniciar escrevendo um caso de teste para o método Get em nosso serviço.
Em nossa API temos o serviço TarefaService que possui o seguinte código :
public class TarefaService :
ITarefaService { private readonly AppDbContext _context; public TarefaService(AppDbContext context) { _context = context; } public async Task<List<Tarefa>> GetTarefasAsync() { return await _context.Tarefas.ToListAsync(); }
public async
Task CriaTarefaAsync(Tarefa novaTarefa) |
Nosso método Get TarefasAsync() retorna uma lista de objetos Tarefa e dependend do contexto definido por _context.
Vamos criar um arquivo de teste no projeto MinhaApi.Tests , na pasta Services, chamado TestTarefaService.cs e incluir o código abaixo :
public class TestTarefaService
{
protected readonly AppDbContext _context;
public TestTarefaService() : IDisposable
{
var options = new DbContextOptionsBuilder<AppDbContext>()
.UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString())
.Options;
_context = new AppDbContext(options);
_context.Database.EnsureCreated();
}
[Fact]
public async Task GetTarefasAsync_ReturnTarefaCollection()
{
/// Arrange
_context.Tarefas.AddRange(MockData.TarefasMockData.GetTarefas());
_context.SaveChanges();
var sut = new TarefaService(_context);
/// Act
var result = await sut.GetTarefasAsync();
/// Assert
result.Should().HaveCount(TarefasMockData.GetTarefas().Count);
}
public void Dispose()
{
_context.Database.EnsureDeleted();
_context.Dispose();
}
}
|
Vamos entender o código:
A classe TestTarefaService implementa IDisposable
Em vez de mocar o contexto 'AppDbContext', vamos criar o banco de dados na memória, para que nossos testes sejam mais fáceis e flexíveis. Aqui o construtor é invocado para cada execução do método de teste. Portanto, queremos criar um banco de dados em memória separado para cada método de teste unitário, portanto, temos que definir o nome exclusivo do banco de dados que obteremos usando o 'Guid'.;
Usamos o método EnsureCreated para garantir que o banco de dados existe. Se o banco não existir ele será criado. Se as tabelas não existirem o modelo das entidades será usado para criar as tabelas.;
No método de teste GetTarefasAsync_ReturnTarefaCollection estamos populando a tabela Tarefas do banco de dados em memória com alguns dados e criando o objeto para TarefaService;
Em Act estamos invocando o método de teste sut.GetTarefasAsync() e a seguir estamos verificando a saída conforme o que esperamos
Ao final o método 'Dispose' é executado na conclusão da execução do método do caso de teste. Aqui queremos destruir o banco de dados na memória para que cada caso de teste tenha seu próprio banco de dados na memória.
Executando o caso de teste no Test Explorer iremos obter:
Testando o Controller
Continuando vamos escrever um caso de teste para um método Action Post do nosso controlador TarefasController da API WebApi.
Abaixo temos os métodos do controlador TarefasController:
[Route("api/[controller]")]
[ApiController]
public class TarefasController : ControllerBase
{
private readonly ITarefaService _tarefaService;
public TarefasController(ITarefaService tarefaService)
{
_tarefaService = tarefaService;
}
[Route("tarefas")]
[HttpGet]
public async Task<IActionResult> GetTodasTarefasAsync()
{
var result = await _tarefaService.GetTarefasAsync();
if (result.Count == 0)
{
return NoContent();
}
return Ok(result);
}
[HttpPost]
[Route("novatarefa")]
public async Task<IActionResult> NovaTarefaAsync(Tarefa novaTarefa)
{
await _tarefaService.CriaTarefaAsync(novaTarefa);
return Ok();
}
}
|
Vamos criar dados fictícios para usar no teste do método incluindo o método NovaTarefa abaixo na classe TarefasMockData
public static Tarefa NovaTarefa()
{
return new Tarefa
{
Id = 0,
Nome = "Completar leitura do artigo..",
Concluida = false
};
}
|
A seguir vamos criar o caso de teste para o método NovaTarefaAsync no controlador TestTarefasController :
[Fact]
public async Task NovaTarefaAsync_ShouldCall_ITarefaService_NovaTarefaAsync_UmaVez()
{
/// Arrange
var tarefaService = new Mock<ITarefaService>();
var novaTarefa = TarefasMockData.NovaTarefa();
var sut = new TarefasController(tarefaService.Object);
/// Act
var result = await sut.NovaTarefaAsync(novaTarefa);
/// Assert
tarefaService.Verify(_ => _.CriaTarefaAsync(novaTarefa), Times.Exactly(1));
}
|
Como nosso método 'TarefasController.NovaTarefaAsync()' não retorna nada, para realizar nossos testes aqui determinamos que o método 'TarefaService.CriaTarefaAsync()' seja executado exatamente uma vez.
Executando o caso no Test Explorer teremos :
Creio que você entendeu como realizar os testes de unidade e criar os casos de testes usando o xUnit.
Pegue o projeto aqui : MinhaApi.zip (sem as referências)
"E a vós outros,
que estáveis mortos pelas vossas transgressões e pela incircuncisão da vossa
carne, vos deu vida juntamente com ele, perdoando todos os nossos delitos;"
Colossenses 2:13
Referências: