Árvore de páginas

Você está vendo a versão antiga da página. Ver a versão atual.

Comparar com o atual Ver Histórico da Página

« Anterior Versão 8 Atual »

Construímos o TNF para que as boas praticas e os princípios de um código limpo fossem respeitados.

Para que isso aconteça devemos construir um código que possibilite ser testado tentando obter o máximo de cobertura possível.

Vamos conhecer a estrutura que o TNF oferece para criação de nossos testes unitários e integrados.

Frameworks

Não é uma regra, mas sugerimos os seguintes frameworks para utilização em seu projeto.

Xunit.net

Framework open source, largamente utilizado para realizar testes na plataforma .NET. que suporta todas as tecnologias. Atualmente faz parte do .NET Foundation.

https://xunit.github.io/

Shouldly

Framework com estrutura de asserção. Junto com o Xunit fornece uma gama de métodos de extensão para realizar os asserts e validações de regras, objetos e comportamentos.

https://github.com/shouldly/shouldly

NSubstitute

Framework open source para realização de .NET mocking. Com ele é possível realizar mock de propriedades, classes, interfaces entre outras funcionalidades.

http://nsubstitute.github.io/

Cenário de testes

Todos os cenários descritos a seguir estão dispostos em nosso github no endereço: https://github.com/totvsnetcore/tnf-samples/tree/master/TnfSample-Architecture

Camada de infraestrutura

Nossa aplicação contem em sua camada de infraestrutura dois repositórios de dados: Entity Framework Core e Carol (SAS desenvolvido pela TOTVS).

Entidade no Entity Framework Core e Dto:

Country.cs
[AutoMap(typeof(CountryDto))]
[Table("Countries")]
public class Country : Entity
{
	public const int MaxNameLength = 256;
    [Required]
    [MaxLength(MaxNameLength)]
    public string Name { get; set; }
    public Country()
    {
    }
    public Country(int id, string name)
    {
    	Id = id;
        Name = name;
    }
}
 
public class CountryDto
{
	public string Name { get; set; }
}

Entidade no Carol e Dto:

PresidentEntity.cs
[JsonObject("president")]
public class PresidentEntity : CarolEntity
{
	public string Name { get; set; }
    public string ZipCode { get; set; }
    public override object GetStagingMapping()
    {
    	return new
        {
        	name = "string",
            zipCode = "string"
        };
	}
}
 
public class PresidentDto
{
	public PresidentDto()
    {
    }
    public PresidentDto(string id, string name, string zipCode)
    {
    	Id = id;
        Name = name;
        ZipCode = new ZipCode(zipCode);
	}
    public string Id { get; set; }
    public string Name { get; set; }
    public ZipCode ZipCode { get; set; }
}

Camada de Domínio

Serviço WhiteHouseService responsável pela persistência das entidade de presidentes no Carol.

Abaixo temos a implementação do serviço WhiteHouseService usando um repositório chamado IWhiteHouseRepositoriy implementado pela camada de infraestrutura consumindo dados do Carol.

WhiteHouseService.cs
// Domain service interface
public interface IWhiteHouseService : IDomainService
{
    Task<DtoResponseBase<PresidentDto>> InsertPresidentAsync(PresidentDto request);
}
 
// Domain service
public class WhiteHouseService : DomainService<IWhiteHouseRepository>, IWhiteHouseService
{
    private readonly IEventBus _eventBus;
 
    public WhiteHouseService(IWhiteHouseRepository repository, IEventBus eventBus)
        : base(repository)
    {
        _eventBus = eventBus;
    }
 
    public Task<DtoResponseBase<PresidentDto>> InsertPresidentAsync(PresidentDto request)
    {
        var response = new DtoResponseBase<PresidentDto>();
        var builder = new PresidentBuilder()
            .WithId(item.Id)
            .WithName(item.Name);
 
        var build = builder.Build();
        if (!build.Success)
        {
            response.AddNotifications(build.Notifications);
            return response;
        }
 
        var presidentCreated = await Repository.InsertPresidentAsync(request);
        response.Data = presidentCreated;
 
        // Trigger event
        _eventBus.Trigger(new PresidentCreatedEvent(presidentCreated));
        return response;
    }
}

Além da validação da entidade nosso caso de testes faz uso de Domain Events e dispara um evento após inserir a entidade de presidente.

PresidentBuilder.cs
internal class PresidentBuilder : Builder<President>
{
    public PresidentBuilder()
        : base()
    {
    }
    public PresidentBuilder(President instance)
        : base(instance)
    {
    }
    public PresidentBuilder WithId(string id)
    {
        Instance.Id = id;
        return this;
    }
    public PresidentBuilder WithName(string name)
    {
        Instance.Name = name;
        return this;
    }
    public override BuilderResponse<President> Build()
    {
        // Entity specifications
        var shouldHaveName = new PresidentShouldHaveNameSpecification();
 
        if (!shouldHaveName.IsSatisfiedBy(Instance))
        {
            var notificationMessage = LocalizationHelper.GetString(
                AppConsts.LocalizationSourceName,
                President.Error.PresidentNameMustHaveValue);
            Response.AddNotification(President.Error.PresidentNameMustHaveValue, notificationMessage);
        }
 
        return base.Build();
    }
}

Camada de aplicação

Serviços de aplicação em nosso cenário:

  • CountryAppService: Consumindo dados do Entity Framework Core utilizando a criação de CRUD padrão do TNF.
ICountryAppService.cs
public interface ICountryAppService : IAsyncCrudAppService<CountryDto>
{
}
  • WhiteHouseAppService: Consumindo dados do Carol
IWhiteHouseAppService.cs
public interface IWhiteHouseAppService : IApplicationService
{
	Task<PagingDtoResponse<PresidentDto>> GetAllPresidents(GellAllPresidentsRequestDto request);
    Task<PresidentDto> GetPresidentById(string id);
    Task<DtoResponseBase<List<PresidentDto>>> InsertPresidentAsync(List<PresidentDto> dtos, bool sync = true);
    Task<DtoResponseBase> UpdatePresidentAsync(PresidentDto dto);
    Task<DtoResponseBase> DeletePresidentAsync(string id);
}

Camada de Serviços

API com padrão RESTful para os dois serviços de aplicação criados expostos com ASP NET Core.

  • Sem rótulos