.github/skills/policy-emulator-testing/SKILL.md
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/.
npx skillsauth add azure/azure-api-management-policy-toolkit policy-emulator-testingInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This skill describes how to write tests for gateway emulator policy handlers in the Azure API Management policy toolkit.
test/Test.Testing/Emulator/Policies/{PolicyName}Tests.cs// 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};
}
}
Test.Emulator.Emulator.Policies (matches existing test convention){PolicyName}Tests[TestClass], [TestMethod])new SimpleDocument().AsTestDocument() extension method (or new TestDocument(new SimpleDocument()) — both are equivalent)IDocument with all four section methods. Unused sections have empty bodies.test.RunInbound(), test.RunOutbound(), test.RunBackend(), test.RunOnError()Each policy must have tests covering:
Create a document with the policy call, run through TestDocument, assert context state changes:
[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");
}
Verify that SetupInbound() (or appropriate section) .{PolicyName}().WithCallback(...) correctly overrides default behavior:
[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");
}
For policies called multiple times with different configs in the same section:
[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...
}
When the handler depends on existing context state:
[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");
}
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:
[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():
[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");
}
If the policy is available in multiple sections, add one test per section:
[TestMethod]
public void ShouldWorkInOutboundSection()
{
var test = new Outbound{PolicyName}().AsTestDocument();
test.RunOutbound();
test.Context.{assertion};
}
test.SetupInbound()
.AuthenticationManagedIdentity()
.WithTokenProviderHook((resource, clientId) => $"{resource}{clientId}/token");
test.SetupInbound()
.AuthenticationManagedIdentity()
.ReturnsToken("mock-token");
test.SetupCacheStore()
.WithExternalCacheSetup()
.WithExternalCacheValue("key", "test");
test.SetupCacheStore().WithInternalCacheValue("key", "test");
var example = new ResponseExample(200, "{ \"ok\": true }", "application/json");
test.SetupResponseExampleStore().Add(test.Context, example);
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.# 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"
tools
Conventions and patterns for writing policy compilation tests in the Azure API Management policy toolkit. Use this skill when creating or modifying test files in test/Test.Core/Compiling/.
tools
Conventions and patterns for creating gateway emulator policy handlers in the Azure API Management policy toolkit. Use this skill when creating or modifying handler classes in src/Testing/Emulator/Policies/.
tools
Conventions and patterns for creating policy compilers in the Azure API Management policy toolkit. Use this skill when creating or modifying compiler classes in src/Core/Compiling/Policy/.
tools
Reference guide for the Azure API Management policy toolkit codebase structure. Use this skill when you need to find existing policies, infrastructure, or naming conventions.