Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
A tartós vezénylések egységtesztelése segít az üzleti logika ellenőrzésében és a hibák korai észlelésében. A vezénylések több tevékenységet koordinálnak, és gyorsan összetettek lehetnek, így a tesztek védelmet nyújtanak a regressziók ellen a munkafolyamat fejlődésével.
Válassza ki a projektnek megfelelő lapot: Durable Functions ha Azure Functions használ, vagy Durable Task SDK-k ha az önálló SDK-t Azure Functions nélkül használja.
Durable Functions segítségével a vezénylőket, tevékenységeket és az ügyfél (trigger) függvényeket a keretrendszer által biztosított környezeti objektumok mokkolásával tesztelheti, és közvetlenül meghívhatja a függvényeket. Ez a módszer elkülöníti az üzleti logikát a Azure Functions futtatókörnyezettől.
Íme egy minimális C#-vezénylési teszt a minta megjelenítéséhez:
[Fact]
public async Task MyOrchestrator_CallsActivity()
{
var contextMock = new Mock<TaskOrchestrationContext>();
contextMock.Setup(x => x.CallActivityAsync<string>(
It.IsAny<TaskName>(), It.IsAny<string>(), It.IsAny<TaskOptions>()))
.ReturnsAsync("result");
var result = await MyOrchestrator.Run(contextMock.Object);
Assert.Equal("result", result);
}
A cikk további része részletesen ismerteti a C# és a Python mintáját.
A különálló Durable Task SDK-k beépített tesztinfrastruktúrát biztosítanak, amely külső függőségek nélkül futtat vezényléseket a memóriában. Orchesztrálókat és tevékenységeket regisztrálhat egy tesztmunkással, és ütemezheti az orchesztrálásokat tesztügyfél segítségével, valamint ellenőrizheti az eredményeket. A C# és a JavaScript esetében nem szükséges mockolás. Python generátoralapú megközelítést használ manuális eredményinjektálással.
Íme egy minimális C#-teszt a minta megjelenítéséhez:
[Fact]
public async Task MyOrchestrator_Completes()
{
await using var host = await DurableTaskTestHost.StartAsync(tasks =>
{
tasks.AddOrchestrator<MyOrchestrator>();
tasks.AddActivity<MyActivity>();
});
string id = await host.Client.ScheduleNewOrchestrationInstanceAsync(nameof(MyOrchestrator));
var result = await host.Client.WaitForInstanceCompletionAsync(id, getInputsAndOutputs: true);
Assert.Equal(OrchestrationRuntimeStatus.Completed, result.RuntimeStatus);
}
A cikk további része részletesen ismerteti ezt a mintát a C#, a Python és a JavaScript esetében.
Prerequisites
- xUnit – tesztelési keretrendszer
- Moq — tesztkörnyezet szimuláló keretrendszer
- Az .NET izolált feldolgozómodell ismerete
- xUnit – tesztelési keretrendszer
- A
Microsoft.DurableTask.InProcessTestHostNuGet-csomag (1.0.0-s vagy újabb verzió)
Orchestrátorfüggvények tesztelése
Az Orchestrator függvények koordinálják a tevékenységeket, az időzítőket és a külső eseményeket. Ezek általában a legtöbb üzleti logikát tartalmazzák, és a legtöbbet ki tudják használni az egységtesztelésből.
Szimulálja az orkesztációs környezetet a tevékenységhívások visszatérési értékeinek vezérlésére. Ezután hívja meg közvetlenül a vezénylőt, és ellenőrizze a kimenetet.
Fontolja meg ezt az orchestrator-t, amely háromszor hív meg egy tevékenységet:
[Function(nameof(HelloCitiesOrchestration))]
public static async Task<List<string>> HelloCities(
[OrchestrationTrigger] TaskOrchestrationContext context)
{
var outputs = new List<string>
{
await context.CallActivityAsync<string>(nameof(SayHello), "Tokyo"),
await context.CallActivityAsync<string>(nameof(SayHello), "Seattle"),
await context.CallActivityAsync<string>(nameof(SayHello), "London")
};
return outputs;
}
A Moq használatával szimulálhatja TaskOrchestrationContext és beállíthatja az egyes tevékenységhívások várható visszatérési értékeit.
Note
A It.Is<TaskName>(...) minta azért szükséges, mert CallActivityAsync nem egyszerű sztringet, hanem szerkezetet fogad el TaskName . A Moq-nak szüksége van explicit típusegyezésre.
[Fact]
public async Task HelloCities_ReturnsExpectedGreetings()
{
var contextMock = new Mock<TaskOrchestrationContext>();
// Mock each activity call to return a known value
contextMock.Setup(x => x.CallActivityAsync<string>(
It.Is<TaskName>(n => n.Name == nameof(SayHello)),
It.Is<string>(n => n == "Tokyo"),
It.IsAny<TaskOptions>())).ReturnsAsync("Hello Tokyo!");
contextMock.Setup(x => x.CallActivityAsync<string>(
It.Is<TaskName>(n => n.Name == nameof(SayHello)),
It.Is<string>(n => n == "Seattle"),
It.IsAny<TaskOptions>())).ReturnsAsync("Hello Seattle!");
contextMock.Setup(x => x.CallActivityAsync<string>(
It.Is<TaskName>(n => n.Name == nameof(SayHello)),
It.Is<string>(n => n == "London"),
It.IsAny<TaskOptions>())).ReturnsAsync("Hello London!");
var result = await HelloCitiesOrchestration.HelloCities(contextMock.Object);
Assert.Equal(3, result.Count);
Assert.Equal("Hello Tokyo!", result[0]);
Assert.Equal("Hello Seattle!", result[1]);
Assert.Equal("Hello London!", result[2]);
}
Az DurableTaskTestHost használható az orchestrációk memóriabeli futtatására. Regisztrálja a produkciós vezénylőt és a tevékenységi osztályokat, ütemezze a vezénylést, és ellenőrizze az eredményt.
Ezeket a termelési osztályokat figyelembe véve:
class HelloCitiesOrchestrator : TaskOrchestrator<string, List<string>>
{
public override async Task<List<string>> RunAsync(
TaskOrchestrationContext context, string input)
{
var outputs = new List<string>
{
await context.CallActivityAsync<string>(nameof(SayHelloActivity), "Tokyo"),
await context.CallActivityAsync<string>(nameof(SayHelloActivity), "Seattle"),
await context.CallActivityAsync<string>(nameof(SayHelloActivity), "London")
};
return outputs;
}
}
class SayHelloActivity : TaskActivity<string, string>
{
public override Task<string> RunAsync(TaskActivityContext context, string name)
{
return Task.FromResult($"Hello {name}!");
}
}
Regisztrálja őket közvetlenül a teszthelygépen:
[Fact]
public async Task HelloCities_ReturnsExpectedGreetings()
{
await using var host = await DurableTaskTestHost.StartAsync(tasks =>
{
tasks.AddOrchestrator<HelloCitiesOrchestrator>();
tasks.AddActivity<SayHelloActivity>();
});
string instanceId = await host.Client.ScheduleNewOrchestrationInstanceAsync(
nameof(HelloCitiesOrchestrator));
OrchestrationMetadata result = await host.Client.WaitForInstanceCompletionAsync(
instanceId, getInputsAndOutputs: true);
Assert.Equal(OrchestrationRuntimeStatus.Completed, result.RuntimeStatus);
var output = result.ReadOutputAs<List<string>>();
Assert.Equal(3, output.Count);
Assert.Equal("Hello Tokyo!", output[0]);
Assert.Equal("Hello Seattle!", output[1]);
Assert.Equal("Hello London!", output[2]);
}
DurableTaskTestHost egy teljes mértékben memóriában futó vezénylési motort futtat. Nincs szükség külső szolgáltatásokra vagy kiegészítő folyamatokra.
Tevékenységfüggvények tesztelése
A tevékenységfüggvények tartalmazzák a tényleges munkát – API-k meghívását, adatok feldolgozását vagy külső rendszerekkel való interakciót. Ezek a legegyszerűbben tesztelendő függvénytípusok, mivel nem rendelkeznek keretrendszerspecifikus visszajátszási viselkedésekkel.
A Azure Functions tevékenységfüggvényei bemenetet kapnak, és opcionálisan egy FunctionContext. Tesztelje őket, mint bármely más függvényt:
[Function(nameof(SayHello))]
public static string SayHello(
[ActivityTrigger] string name, FunctionContext executionContext)
{
return $"Hello {name}!";
}
[Fact]
public void SayHello_ReturnsExpectedGreeting()
{
var result = HelloCitiesOrchestration.SayHello("Tokyo", Mock.Of<FunctionContext>());
Assert.Equal("Hello Tokyo!", result);
}
A tevékenységfüggvények környezeti objektumot és bemenetet kapnak. A környezet olyan metaadatokat biztosít, mint a vezénylési azonosító és a feladatazonosító, de a legtöbb tesztnek nincs rá szüksége.
SayHelloActivity A vezénylői példa osztályának használatával közvetlenül hívjon RunAsync meg egy példakörnyezetet:
[Fact]
public async Task SayHello_ReturnsExpectedGreeting()
{
var activity = new SayHelloActivity();
var contextMock = new Mock<TaskActivityContext>();
var result = await activity.RunAsync(contextMock.Object, "Tokyo");
Assert.Equal("Hello Tokyo!", result);
}
Ha használja DurableTaskTestHost, a tevékenységek a vezénylési teszt részeként is futnak. Nincs szükség külön tevékenységtesztre, kivéve, ha a tevékenység összetett logikával rendelkezik.
Az ügyfél programfunkcióinak tesztelése
Az ügyfélfüggvények (más néven triggerfüggvények) elindítják a vezényléseket, és kezelik a példányokat. A tartós ügyfélkapcsolatot használják, hogy kapcsolatba lépjenek a vezénylési motorral.
Vegye tekintetbe ezt az HTTP-eseményindítót, amely folyamatvezérlést indít el.
[Function("HelloCitiesOrchestration_HttpStart")]
public static async Task<HttpResponseData> HttpStart(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestData req,
[DurableClient] DurableTaskClient client,
FunctionContext executionContext)
{
string instanceId = await client.ScheduleNewOrchestrationInstanceAsync(
nameof(HelloCitiesOrchestration));
return await client.CreateCheckStatusResponseAsync(req, instanceId);
}
Mock DurableTaskClient a jól ismert példányazonosító visszaadásához:
[Fact]
public async Task HttpStart_ReturnsAccepted()
{
var durableClientMock = new Mock<DurableTaskClient>("testClient");
var functionContextMock = new Mock<FunctionContext>();
var instanceId = "test-instance-id";
durableClientMock
.Setup(x => x.ScheduleNewOrchestrationInstanceAsync(
It.IsAny<TaskName>(),
It.IsAny<object>(),
It.IsAny<StartOrchestrationOptions>(),
It.IsAny<CancellationToken>()))
.ReturnsAsync(instanceId);
var mockRequest = CreateMockHttpRequest(functionContextMock.Object);
var responseMock = new Mock<HttpResponseData>(functionContextMock.Object);
responseMock.SetupGet(r => r.StatusCode).Returns(HttpStatusCode.Accepted);
durableClientMock
.Setup(x => x.CreateCheckStatusResponseAsync(
It.IsAny<HttpRequestData>(),
It.IsAny<string>(),
It.IsAny<CancellationToken>()))
.ReturnsAsync(responseMock.Object);
var result = await HelloCitiesOrchestration.HttpStart(
mockRequest, durableClientMock.Object, functionContextMock.Object);
Assert.Equal(HttpStatusCode.Accepted, result.StatusCode);
}
Ügyfélműveletek tesztelése
Önálló Durable Task SDK-k esetén az ügyfélműveletek (vezénylések ütemezése, állapot lekérdezése, események kiváltása) ugyanazt használják, mint TestOrchestrationClient a vezénylő tesztekben. Nincs külön ügyfélfüggvény – közvetlenül meghívja az ügyfél API-t.
DurableTaskTestHost
host.Clientteszi elérhetővé , ami egy teljesen működőképes DurableTaskClient. Használatával tesztelheti az ügyfélszintű műveleteket, például az ütemezést, a lekérdezést vagy a vezénylések leállítását:
[Fact]
public async Task Client_CanQueryOrchestrationStatus()
{
await using var host = await DurableTaskTestHost.StartAsync(tasks =>
{
tasks.AddOrchestrator<HelloCitiesOrchestrator>();
tasks.AddActivity<SayHelloActivity>();
});
string instanceId = await host.Client.ScheduleNewOrchestrationInstanceAsync(
nameof(HelloCitiesOrchestrator));
// Query status while the orchestration runs
OrchestrationMetadata metadata = await host.Client.WaitForInstanceCompletionAsync(
instanceId, getInputsAndOutputs: true);
Assert.Equal(OrchestrationRuntimeStatus.Completed, metadata.RuntimeStatus);
Assert.Equal(instanceId, metadata.InstanceId);
}