Testes de Integração

Cada projeto gerado a partir dos templates inclui um <YourProject>.Tests.Integration projeto, cabeado e pronto para rodar. Seus testes vão contra um ambiente Dataverse real em vez de mocks, porque a maior parte do que quebra em um portal fica nas costuras que um mock substitui — tradução de consultas, metadados, formatação, permissões. Duas classes base são fornecidas, uma para cada lado disso.

O que tem no Projeto

O template vem esses arquivos; eles são fontes comuns no seu repositório, então alterem-nos livremente.

Arquivo Propósito
PortalEndpointTestBase.cs Inicializa seu portal na memória e expõe um HttpClient contra ele. Derive disso para testes de endpoint e permissões.
TestBase.cs Constrói um contêiner de serviço com uma conexão autenticada do Dataverse. Derive disso para chamar seus próprios serviços e lógica diretamente.
TestAuthentication.cs O esquema de autenticação de teste e o TestUserContext que decide para quem uma requisição é executada.
appsettings.json, xunit.runner.json Configurações não secretas, e a configuração do xunit runner que mantém as coleções seriadas.
ExampleTests.cs, README.md Exemplos funcionais de ambas as bases (pulando até apontar para registros reais), e uma referência local curta.

Escolhendo uma Base

Os dois são complementares — testam camadas diferentes, e um conjunto saudável usa ambos.

Configuração e Segredos

Aponte D365:Url para o ambiente contra o qual os testes devem rodar em appsettings.json — um ambiente de desenvolvimento ou descartável, já que os testes criam e excluem registros. Credenciais vêm de segredos de usuário, e o projeto de teste declara deliberadamente o mesmo UserSecretsId que o projeto web, então um portal que já roda localmente não precisa de mais nada. Para defini-las explicitamente:

Fontes são sobrepostas appsettings.json → segredos de usuário → variáveis de ambiente, então um agente de build pode fornecer tudo através de variáveis de ambiente (D365__ClientSecretusando o duplo sublinhado) sem tocar em um arquivo. Nunca coloque o segredo do cliente em appsettings.json, que é commitado.

Nota

Você não precisa de uma chave de licença para rodar testes. O host em memória ouve em um endereço de loopback, e o loopback é licenciado sem um — sem registro do site do portal e sem necessidade de dupla de teste.

Testando Endpoints e Permissões

Derive de PortalEndpointTestBase e faça requisições com Client. As requisições começam anônimas, que é o padrão correto para afirmar que um endpoint afasta chamadores anônimos. Redirecionamentos não são seguidos, então um teste pode afirmar em um 302 em vez da página em que ele cairia.

Atuando como Usuário

SignInAs é a que deve ser alcançada. Ele faz stubs apenas na etapa de credencial — o principal que emite carrega as mesmas reivindicações que um login real emite, então a autorização, os manipuladores de permissões e toda extensão de leitura de reivindicações se comportam como em produção. Sem senha, sem provisionamento, e pode mudar de identidade entre requisições em um único teste.

LoginAsync Posta credenciais reais no endpoint de login e mantém o cookie, para quando o próprio caminho de login estiver sendo testado. Ele precisa de um contato com senha e um e-mail confirmado, então é mais lento; os dois coexistem e a base volta ao cookie real sempre que nenhum usuário imitado é definido.

Nota

LoginAsync precisa dos endpoints de autenticação JSON, que são mapeados para os hosts React e Blazor WebAssembly/Auto. Um projeto Blazor renderizado por servidor faz login por meio de posts de formulário nas páginas da conta Razor, então /api/auth/login não é mapeado ali e LoginAsync retorna 404 — use SignInAs, que funciona em todos os hosts.

Preparação, Desmontagem e Substituições

Três ganchos cobrem as necessidades habituais. ConfigureTestServices Executa após os próprios registros da sua aplicação, então um Replace lá vence Program.cs — a forma de posicionar um falso para uma dependência de saída. OnInitializedAsync e OnDisposingAsync coloque cada teste entre parchetes para seed e limpeza, e a desmontagem roda mesmo quando um teste falha.

Importante

Esses testes iniciam seu portal, então qualquer coisa que o impeda de começar também os para. Em particular, com a autorização aprimorada ativada, o host valida o ID do site configurado na inicialização e falha com orientação até que um id real powerpagesite seja fornecido — a mesma pré-condição de rodar o portal.

Serviços de Teste e Lógica

Derive de TestBase, registrando o que o código sob teste precisa e resolvendo. O cliente Dataverse já está autenticado.

Passe um ID de usuário para CreateOrganizationService(userId) se passar — O Dataverse então aplica os próprios privilégios desse usuário, que é como verificar o acesso em nível de registro pelo lado dos dados em vez de por um endpoint.

CreateWebApiHttpClientAsync() retorna um cliente autenticado contra a API Web do Dataverse (/api/data/v9.2/) para asserções que são mais fáceis de expressar em OData do que através do SDK. Ele precisa Azure:TenantId de configuração, além do id do cliente e do segredo.

Como os Testes Funcionam

Execute-as com dotnet test, ou pelo explorador de testes do seu IDE. Algumas características que valem a pena conhecer antes de escrever muitas:

Melhores práticas

Aponte o conjunto para um ambiente de desenvolvimento, nunca para produção. Essas são gravações reais contra dados reais, e um teste que exclui o que foi criado apagará o registro real se você mirar em um.