Skip to main content

policy-emulator-testing

Conventions and patterns for writing gateway emulator policy handler tests in the Azure API Management policy toolkit. Use this skill when creating or modifying test files in test/Test.Testing/Emulator/Policies/.

Informações da origem

Repositório
Azure/azure-api-management-policy-toolkit
Última atividade na origem
8 de março de 2026 às 18:53
Idioma detectado do SKILL.md
inglês
Estrelas
95
Forks
37

Opções de instalação

Por padrão, está selecionado o prompt que primeiro revisa a origem. Você pode mudar para um comando direto ou baixar uma cópia local.

Revise os arquivos de origem

Leia o SKILL.md e os arquivos complementares exibidos pelo SkillsMP antes de decidir se vai instalar.

Exibindo SKILL.md

SKILL.md
Instruções da origem · Visualização somente leitura
name
policy-emulator-testing
description
Conventions and patterns for writing gateway emulator policy handler tests in the Azure API Management policy toolkit. Use this skill when creating or modifying test files in test/Test.Testing/Emulator/Policies/.
# Policy Emulator Testing Patterns This skill describes how to write tests for gateway emulator policy handlers in the Azure API Management policy toolkit. ## Test File — `test/Test.Testing/Emulator/Policies/{PolicyName}Tests.cs` ### File Template ```csharp // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. namespace Test.Emulator.Emulator.Policies; [TestClass] public class {PolicyName}Tests { // Inner document class implementing IDocument class Simple{PolicyName} : IDocument { public void Inbound(IInboundContext context) { context.{PolicyName}(new {PolicyName}Config { // config properties }); } public void Outbound(IOutboundContext context) { } public void Backend(IBackendContext context) { } public void OnError(IOnErrorContext context) { } } [TestMethod] public void Should{ExpectedBehavior}() { // Arrange var test = new Simple{PolicyName}().AsTestDocument(); // Act test.RunInbound(); // Assert (using FluentAssertions) test.Context.{assertion}; } } ``` ### Key Conventions - **Namespace**: `Test.Emulator.Emulator.Policies` (matches existing test convention) - **Class name**: `{PolicyName}Tests` - **Framework**: MSTest (`[TestClass]`, `[TestMethod]`) - **Assertions**: FluentAssertions - **Test document creation**: `new SimpleDocument().AsTestDocument()` extension method (or `new TestDocument(new SimpleDocument())` — both are equivalent) - **Inner document classes** implement `IDocument` with all four section methods. Unused sections have empty bodies. - **Section execution**: `test.RunInbound()`, `test.RunOutbound()`, `test.RunBackend()`, `test.RunOnError()` ## Required Test Coverage Each policy must have tests covering: ### 1. Basic Execution Create a document with the policy call, run through `TestDocument`, assert context state changes: ```csharp [TestMethod] public void ShouldModifyContextState() { var test = new SimpleSetStatus().AsTestDocument(); test.RunInbound(); test.Context.Response.StatusCode.Should().Be(200); test.Context.Response.StatusReason.Should().Be("OK"); } ``` ### 2. Callback Override Verify that `SetupInbound()` (or appropriate section) `.{PolicyName}().WithCallback(...)` correctly overrides default behavior: ```csharp [TestMethod] public void ShouldExecuteCallback() { var test = new Simple{PolicyName}().AsTestDocument(); test.SetupInbound() .{PolicyName}() .WithCallback((context, config) => { context.Variables["test"] = "value"; }); test.RunInbound(); test.Context.Variables.Should().ContainKey("test") .WhoseValue.Should().Be("value"); } ``` ### 3. Predicate-Based Mock For policies called multiple times with different configs in the same section: ```csharp [TestMethod] public void ShouldSelectCorrectCallback() { var test = new Multi{PolicyName}().AsTestDocument(); test.SetupInbound() .{PolicyName}((ctx, config) => config.SomeProperty == "A") .WithCallback((ctx, cfg) => { /* handle A */ }); test.SetupInbound() .{PolicyName}((ctx, config) => config.SomeProperty == "B") .WithCallback((ctx, cfg) => { /* handle B */ }); test.RunInbound(); // Assert... } ``` ### 4. Pre-configured Context When the handler depends on existing context state: ```csharp [TestMethod] public void ShouldHandleExistingHeaders() { var test = new Simple{PolicyName}().AsTestDocument(); test.Context.Request.Headers["Content-Type"] = ["application/json"]; test.RunInbound(); test.Context.Request.Headers.Should().ContainKey("Content-Type"); } ``` ### 5. Error/Exception Scenarios Not all policies support `.WithError()`. This API is specific to certain mock providers (e.g., `MockAuthenticationManagedIdentityProvider`). For policies without a dedicated error API, simulate errors via callbacks: ```csharp [TestMethod] public void ShouldSimulateError() { var test = new Simple{PolicyName}().AsTestDocument(); test.SetupInbound() .{PolicyName}() .WithCallback((context, config) => { context.Response.StatusCode = 500; context.Response.StatusReason = "Internal Server Error"; throw new FinishSectionProcessingException(); }); test.RunInbound(); test.Context.Response.StatusCode.Should().Be(500); } ``` For authentication policies that have `.WithError()`: ```csharp [TestMethod] public void ShouldThrowOnError() { var test = new SimpleAuthenticationManagedIdentity().AsTestDocument(); test.SetupInbound() .AuthenticationManagedIdentity() .WithError("InternalServerError"); var ex = Assert.ThrowsException<PolicyException>(() => test.RunInbound()); ex.Policy.Should().Be("AuthenticationManagedIdentity"); } ``` ### 6. Multi-Section Tests If the policy is available in multiple sections, add one test per section: ```csharp [TestMethod] public void ShouldWorkInOutboundSection() { var test = new Outbound{PolicyName}().AsTestDocument(); test.RunOutbound(); test.Context.{assertion}; } ``` ## Mock Setup Patterns ### Token Provider Hook (Authentication policies) ```csharp test.SetupInbound() .AuthenticationManagedIdentity() .WithTokenProviderHook((resource, clientId) => $"{resource}{clientId}/token"); ``` ### Return Value (Authentication, Cache) ```csharp test.SetupInbound() .AuthenticationManagedIdentity() .ReturnsToken("mock-token"); ``` ### Cache Store Setup ```csharp test.SetupCacheStore() .WithExternalCacheSetup() .WithExternalCacheValue("key", "test"); test.SetupCacheStore().WithInternalCacheValue("key", "test"); ``` ### Response Example Store (MockResponse) ```csharp var example = new ResponseExample(200, "{ \"ok\": true }", "application/json"); test.SetupResponseExampleStore().Add(test.Context, example); ``` ## Test Infrastructure Tests rely on shared infrastructure that you do not need to modify: - **`TestDocument`** (`src/Testing/TestDocument.cs`) — Wraps an `IDocument` and executes sections through proxies. Catches `FinishSectionProcessingException` gracefully. - **`.AsTestDocument()`** extension method — Creates `TestDocument` from `IDocument`. - **`SetupInbound()`/`SetupOutbound()`/etc.** — Returns `MockPoliciesProvider<TSection>` for fluent mock configuration. - **`GatewayContext`** (`src/Testing/GatewayContext.cs`) — Contains mock request/response, variables, and emulator stores. - **`Usings.cs`** (`test/Test.Testing/Usings.cs`) — Global usings for `FluentAssertions` and `Microsoft.VisualStudio.TestTools.UnitTesting`. ## Build and Test Commands ```bash # Run all emulator tests dotnet test --project test/Test.Testing # Run tests for a specific policy dotnet test --project test/Test.Testing --filter "FullyQualifiedName~{PolicyName}Tests" ```
Ver no GitHub