Há poucos dias atrás fiz uma extrementação Para Integradar Meus Testes COM O SQL Server.
Мотиваção.
O que me levou escrever Esse Tipo de Teste Foi:
- Quero Escrever UM Testes Que Seja O Mais Aderente Ao Ambiente de Produção — Ou Seja, SE VAI RODAR EM SQL Server — Tenho Que Escrever UM Testes Que Rode EM SQL Server.
- Quero Testar Communitas Mais Complys;
- Quero Testar Cada Método Da Minha Classe de Repositório, COM Cenário Próprio, SEM Precisar Rodar o Sistema Inteiro Para Fazer Realizar Este Teste;
- Возможность Testes Transacionais
Para Radar OS Testes Segui OS Seguintes Passos:
- Montei UM SQL Server Em UM-контейнер;
- ESCREVI UM Código Para Criação da Estrutura de Banco, Cenário E Execução Dos Teste de Repositórios;
- Escrevi OS Testes Propramente Ditos;
- Configurei o Pobile DO DO AZURE PARA SUBIR UMA Instância DO SQL Server EM Tempo de Build Antes de Rodar OS Testes Integrados Com Repositórios.
Exemplo Do Método de Repositório Que Quero Testar
public async Task> GetByEmailAsync(string email) { var query = @" SELECT u.Id, u.FirstName, u.LastName, u.PersonalIdentificationNumber, u.Email, u.ProfileCode, u.DateCreated FROM [dbo].[User] u WHERE u.Email = @Email AND u.TenantId = @TenantId"; return await _dapperContext.DapperConnection .QueryAsync ( query, new { Email = email, TenantId = this.TenantId() }); }
Sqlserver no meu ambiente de desenvolvimento
CRIEI UM-контейнер (Docker) Para Instância DO SQL Server. Para Subir O. SQL Server Disponibilizo Meu Docker-Compose que Utilizei Para Inciblização do контейнер;
Meu Sistema Operational Eo Windows Então, Utilizei o Докер Для Windows Disponível Aqui.
Salve Ur Arquivo EM Alguma Pasta No Seu Commentador Com Esse Conteúdo. Нет Meu Ambiente, Salvei Aqui [ C: _devz \ dockers \ sqlserver]
Docker-Compose.yml.yml.yml
version: '3' services: db: image: mcr.microsoft.com/mssql/server:2017-latest-ubuntu environment: SA_PASSWORD: "Q1w2e3r4!" ACCEPT_EULA: Y MSSQL_PID: Express ports: - "1433:1433" volumes: - mssql-volume:/var/lib/mssql networks: - mssql_docknet networks: mssql_docknet: driver: bridge volumes: mssql-volume:
Контейнер Para Executar O, выполните не подсказку COMO ABAIXO:
> cd C:\_devz\Dockers\sqlserver [Esse é o local onde está o docker-compose.yml] > docker-compose up –d
Código Para Estrutura E Conexão Com Banco de Dados
Para Que Meu Teste Funcionasse Precisei de UMA Instância DO SQL Server Funcionando — Instância Que Configurei Acima;
Para Ter Cenários e Testes Независимые, АНТЕС Que OS Testes Fossem Executados:
- Criei UMA Classe de Contexto Compartilhado Que o Xunit Disponibiliza;
- Эссе контекторская кримия О Банко де Дадо;
- Esse Contexto Cria как Tabelas Configuradas не существует;
[CollectionDefinition("DatabaseTestCollection")] public class DatabaseCollection : ICollectionFixture{ }
COM ESSA CLASSE EU DEASTI UM CONTEXTO GLOBAL PARA TODOS OS MEUS TESTES. Essa Classe é Assim Mesmo — NãO TEM Código Nenhum Em Seu Corpo.
NA CLASSE База данныхFixture Tenho As Informações do Banco de Dados E A A Enactização do Banco;
Nesta Classe Configurei As Informações делает сущность E делает DAPPER; COM ESSAS Informações, Meu Banco de Dados de Teste É CriaDo;
public DapperContext _dapper; public IConfiguration _configuration; public DatabaseFixture() { ////minha string de conexão que se conecta com o container montado var connectionString = $"Server=localhost;Database=gamificacao_test;User ID=sa;Password=Q1w2e3r4!;Trusted_Connection=False;"; ////Adicionei algumas configurações para rastrear problemas de banco ao rodar meus testes ContextOptions = new DbContextOptionsBuilder() .UseSqlServer(connectionString) .EnableSensitiveDataLogging() .UseLoggerFactory(LoggerFactory.Create(builder => { builder.AddDebug(); })) .Options; ////Como se trata de um cenário de testes algumas coisas coloquei em memória por não ser relevante para o testes var myConfiguration = new Dictionary { { "ConnectionStrings:GamificacaoDB", connectionString } }; _configuration = new ConfigurationBuilder() .AddInMemoryCollection(myConfiguration) .Build(); IdentityServiceMock = new Mock (); IdentityServiceMock.Setup(x => x.GetTenantId()) .Returns("Wx1"); Context = new EntityContext(ContextOptions, IdentityServiceMock.Object); _dapper = new DapperContext(_configuration); //// Cria o meu banco de testes InitializeDatabase(); } ////Repositorios da minha API que pretendo testar public ActionRepository ActionRepository { get { return new ActionRepository(Context, _dapper, IdentityServiceMock.Object); } } public UserRepository UserRepository { get { return new UserRepository(Context, _dapper, IdentityServiceMock.Object); } } protected virtual void InitializeDatabase() { using (var context = new EntityContext(ContextOptions, IdentityServiceMock.Object)) { context.Database.EnsureDeleted(); context.Database.EnsureCreated(); } }
O repositório que retendo testar
ESTOU TESTANDO O REPOSITORIOO de Usuários ( UseRepository ). O Método Em Questão Está Utilizando Dapper E Minha Consulta é Muito Smops.
public async Task> GetByEmailAsync(string email) { var query = @" SELECT u.Id, u.FirstName, u.LastName, u.PersonalIdentificationNumber, u.Email, u.ProfileCode, u.DateCreated FROM [dbo].[User] u WHERE u.Email = @Email AND u.TenantId = @TenantId"; return await _dapperContext.DapperConnection .QueryAsync ( query, new { Email = email, TenantId = this.TenantId() }); }
O Темит
Quando instância do sqlserver iniciou nan thenho nenhuma informação nas tabelas para executar os testes. Então, Preciso КРИРСК ЭСКАЗЫ ДАДОС. Para Isso, Utilizei As Mesmas Classes de Criação de objetos que já temos em nossa estrutura. Veja No Teste Abaixo: Criei 1 Usuário.
Para o Contexto DOS Testes Criei Um Método Estendido Para как Estidades. Nesse Método Consigo Inserir No Banco de Dados o que stesta u Estida. ISSO FACILITA OLLUSãO DE DADOS NAS TABELAS SEM Обучение NAS CAMAR O Repositório Para Inserir.
public static class EntityExtensions { public static T Persist( this T entity, EntityContext context) where T : class { context.Add(entity); context.SaveChanges(); return entity; } }
Então, Na linha onde temos Пользователь. Сохраняться (_databasefixture. Контекст) Табела Пользователь Será Persistida.
O mesmo aconteceria com routoS objetos onde chamando o .persist ().
[Fact] public async Task GetByMail_TestAsync() { //Cenario var tiago = new Domain.Models.User { Email = "tiagobrito@wizsolucoes.com.br", FirstName = "Tiago", LastName = "Brito", ProfileCode = "A", PersonalIdentificationNumber = "15476338731" }; tiago.Persist(_databaseFixture.Context); //Execução var userToCompare = await _databaseFixture.UserRepository .GetByEmailAsync("tiagobrito@wizsolucoes.com.br"); ///Validação userToCompare.ElementAt(0).FirstName.Should().Be("Tiago"); userToCompare.ElementAt(0).LastName.Should().Be("Brito"); }
var userToCompare = await _databaseFixture.UserRepository .GetByEmailAsync("tiagobrito@wizsolucoes.com.br");
Na linha acima temos execução do Repositório. Nesta retapa, Тодос О.С. Меюс Дадос Я Эстао Персистидос E, SE ALIMESEI AS TABELA Corretamente E Minha Classe de Repositório Ediver Com A Consuma Correta, ОС Dados Virão. Estamos Testando Apenas Essa Unidade. FICA BEM STRPERS E NãO Preciso Rodar o Sistema Inteiro.
PARA валидар ОС Retornos Utilizamos o que já conheecemos
ЕС Utilizo UMA Biblioteca Para Утверждать Fluente — Тео-нибудь Лейтуру Do Teste Fica Bem Legal. Поде Ser Encontrada Aqui.
userToCompare.ElementAt(0).FirstName.Should().Be("Tiago"); userToCompare.ElementAt(0).LastName.Should().Be("Brito");
Configuração Do Parian Para Testes de Integração COM SQL Server нет лазу
COMO Mencionado No Lameiro Tópico, Utilizo UM Контейнер Para Subir UMA Instancia DO SQL Server Express E Realizar OS Testes. Нет Azure DevOps Fiz o Mesmo: нет Arquivo Azure-Pipelines.yml DO PROJETO DESTEVI O Recurso que Precisava NAS Extensões, Segundo O Novo Modelo de Pipeliel, icitifiquei o serviço que utilizar. Нет Caso, O SQL Server.
# ASP.NET Core # Build a Web project that uses ASP.NET Core. # Add steps that analyze code, save build artifacts, deploy, and more: # https://docs.microsoft.com/azure/devops/pipelines/languages/dotnet-core # YAML reference: # https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema variables: azResourceName: 'meu-projeto' resources: repositories: - repository: dotnettemplate type: git name: meurepositorio/modelos ref: refs/tags/v1.1 containers: - container: mssql image: mcr.microsoft.com/mssql/server:2017-latest-ubuntu ports: - 1433:1433 options: -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=Q1w2e3r4!' -e 'MSSQL_PID=Express' pool: vmImage: 'ubuntu-latest' schedules: - cron: "0 0 * * *" displayName: Build Noturno always: true branches: include: - master trigger: batch: true paths: exclude: - README.md stages: - stage: Build pool: Wiz Hosted Ubuntu 1604 jobs: - job: continueOnError: true services: localhostsqlserver: mssql steps: #Essas linhas com powershell são apenas para testes. podem ser removidas - task: PowerShell@2 displayName: 'delay 10' inputs: targetType: 'inline' script: | # Write your PowerShell commands here. start-sleep -s 10 - task: CmdLine@2 inputs: script: 'sqlcmd -S localhost -d master -U sa -P Q1w2e3r4! -Q "SELECT @@version;"' #Esse template compila aplicações .net - template: dotnetcore.yml@dotnettemplate - stage: Uat condition: and(succeeded(), or(contains(variables['Build.SourceBranch'], 'master'), contains(variables['Build.SourceBranch'], 'releases'))) dependsOn: [Build] jobs: - deployment: environment: staging strategy: runOnce: deploy: steps: - task: AzureRmWebAppDeployment@4 displayName: Publish inputs: ConnectionType: 'AzureRM' azureSubscription: 'xxx' appType: 'webApp' WebAppName: '$(azResourceName)-hml-api' packageForLinux: '$(Pipeline.Workspace)/drop/**/*.zip'
O YML Abaixo é Bem Simplififificado E É O Que Utilizamos Na Wiz. Isso Porque Nossa Equipe de Guantanança Trabalhou Algum Tempo Para Torná-Lo Smarts Assim.
resources: repositories: - repository: coretemplate type: git name: meu/repositorio containers: - container: mssql image: mcr.microsoft.com/mssql/server:2017-latest-ubuntu env: ACCEPT_EULA: Y SA_PASSWORD: Q1w2e3r4! MSSQL_PID: Express ports: - 1433:1433 options: --name mssql pool: vmImage: 'ubuntu-latest' schedules: - cron: "0 0 * * *" displayName: Build Noturno always: true branches: include: - master trigger: batch: true paths: exclude: - README.md extends: template: main.yml@coretemplate parameters: technology: 'dotnetcore' dotnetcoreAppType: 'apiApp' azResourceName: 'gamificacao' azSubscriptionUAT: 'xxx' azSubscriptionPRD: 'xxx' dotnetcoreDotNetVersion: '3.x' dotnetcoreBuildProject: '**/*[API].csproj' dotnetcoreBuildConfiguration: Release dotnetcoreTestProject: '**/*[Tt]ests/*.csproj' dotnetcoreNugetFeed: 09b2821a-2950-4eff-a722-dbc8adf4da55 buildServices: mssql: mssql releaseServices: mssql: mssql
Нет Azure PodeMos Visualizar OS Resultaldos
Оригинал: «https://dev.to/devzwiz/teste-de-integracao-com-sqlserver-e-azure-devops-2cl»