Testování služeb gRPC v ASP.NET Core
Poznámka:
Toto není nejnovější verze tohoto článku. Aktuální verzi najdete v tomto článku ve verzi .NET 9.
Upozorňující
Tato verze ASP.NET Core se už nepodporuje. Další informace najdete v zásadách podpory .NET a .NET Core. Aktuální verzi najdete v tomto článku ve verzi .NET 9.
Důležité
Tyto informace se týkají předběžného vydání produktu, který může být podstatně změněn před komerčním vydáním. Microsoft neposkytuje žádné záruky, výslovné ani předpokládané, týkající se zde uváděných informací.
Aktuální verzi najdete v tomto článku ve verzi .NET 9.
Autor: James Newton-King
Testování je důležitým aspektem vytváření stabilního a udržovatelného softwaru. Tento článek popisuje, jak otestovat služby ASP.NET Core gRPC.
Existují tři běžné přístupy pro testování služeb gRPC:
- Testování jednotek: Testování služeb gRPC přímo z knihovny testování jednotek.
- Testování integrace: Aplikace gRPC je hostovaná v TestServertestovacím serveru v paměti z
Microsoft.AspNetCore.TestHost
balíčku. Služby gRPC jsou testovány jejich voláním pomocí klienta gRPC z knihovny testování jednotek. - Ruční testování: Testování serverů gRPC s ad hoc voláními Informace o používání nástrojů příkazového řádku a uživatelského rozhraní se službami gRPC naleznete v tématu Testování služeb gRPC s gRPCurl a gRPCui v ASP.NET Core.
V testování jednotek je zapojena pouze služba gRPC. Závislosti vložené do služby musí být napodobené. Při testování integrace je součástí testu služba gRPC a její pomocná infrastruktura. To zahrnuje spuštění aplikace, injektáž závislostí, směrování a ověřování a autorizaci.
Příklad testovatelné služby
Pokud chcete předvést testy služeb, projděte si následující službu v ukázkové aplikaci.
Zobrazení nebo stažení ukázkového kódu (postup stažení)
Vrátí TesterService
pozdravy pomocí čtyř typů metod gRPC.
public class TesterService : Tester.TesterBase
{
private readonly IGreeter _greeter;
public TesterService(IGreeter greeter)
{
_greeter = greeter;
}
public override Task<HelloReply> SayHelloUnary(HelloRequest request,
ServerCallContext context)
{
var message = _greeter.Greet(request.Name);
return Task.FromResult(new HelloReply { Message = message });
}
public override async Task SayHelloServerStreaming(HelloRequest request,
IServerStreamWriter<HelloReply> responseStream, ServerCallContext context)
{
var i = 0;
while (!context.CancellationToken.IsCancellationRequested)
{
var message = _greeter.Greet($"{request.Name} {++i}");
await responseStream.WriteAsync(new HelloReply { Message = message });
await Task.Delay(1000);
}
}
public override async Task<HelloReply> SayHelloClientStreaming(
IAsyncStreamReader<HelloRequest> requestStream, ServerCallContext context)
{
var names = new List<string>();
await foreach (var request in requestStream.ReadAllAsync())
{
names.Add(request.Name);
}
var message = _greeter.Greet(string.Join(", ", names));
return new HelloReply { Message = message };
}
public override async Task SayHelloBidirectionalStreaming(
IAsyncStreamReader<HelloRequest> requestStream,
IServerStreamWriter<HelloReply> responseStream,
ServerCallContext context)
{
await foreach (var request in requestStream.ReadAllAsync())
{
await responseStream.WriteAsync(
new HelloReply { Message = _greeter.Greet(request.Name) });
}
}
}
Předchozí služba gRPC:
- Řídí se principem explicitních závislostí.
- Očekává, že injektáž závislostí (DI) poskytne instanci
IGreeter
. - Můžete testovat pomocí napodobené služby pomocí napodobené
IGreeter
architektury objektů, jako je Například Moq. Napodobený objekt je objekt s předem určenou sadou vlastností a chování metod používaných k testování. Další informace najdete v tématu Integrační testy v ASP.NET Core.
Služby gRPC pro testování jednotek
Knihovna testů jednotek může přímo testovat služby gRPC voláním jeho metod. Testy jednotek testuje izolovanou službu gRPC.
[Fact]
public async Task SayHelloUnaryTest()
{
// Arrange
var mockGreeter = new Mock<IGreeter>();
mockGreeter.Setup(
m => m.Greet(It.IsAny<string>())).Returns((string s) => $"Hello {s}");
var service = new TesterService(mockGreeter.Object);
// Act
var response = await service.SayHelloUnary(
new HelloRequest { Name = "Joe" }, TestServerCallContext.Create());
// Assert
mockGreeter.Verify(v => v.Greet("Joe"));
Assert.Equal("Hello Joe", response.Message);
}
Předchozí test jednotek:
- Napodobení
IGreeter
pomocí Moq. - Spustí metodu
SayHelloUnary
se zprávou požadavku a .ServerCallContext
Všechny metody služby majíServerCallContext
argument. V tomto testu je k dispozici typ pomocíTestServerCallContext.Create()
pomocné metody. Tato pomocná metoda je součástí ukázkového kódu. - Vytváří kontrolní výrazy:
- Ověří, že název požadavku je předán .
IGreeter
- Služba vrátí očekávanou zprávu odpovědi.
- Ověří, že název požadavku je předán .
HttpContext
Testování jednotek v metodách gRPC
Metody gRPC mají přístup k požadavku HttpContext pomocí ServerCallContext.GetHttpContext
metody rozšíření. Chcete-li testovat metodu, která používá HttpContext
, musí být kontext nakonfigurován v testovacím nastavení. Pokud HttpContext není nakonfigurovaný, GetHttpContext
vrátí hodnotu null
.
Pokud chcete nakonfigurovat během testovacího HttpContext
nastavení, vytvořte novou instanci a přidejte ji do ServerCallContext.UserState
kolekce pomocí __HttpContext
klíče.
var httpContext = new DefaultHttpContext();
var serverCallContext = TestServerCallContext.Create();
serverCallContext.UserState["__HttpContext"] = httpContext;
Spusťte metody služby s tímto kontextem volání pro použití nakonfigurované HttpContext
instance.
Služby GRPC pro testování integrace
Integrační testy vyhodnocují komponenty aplikace na širší úrovni než testy jednotek. Aplikace gRPC je hostovaná na TestServertestovacím serveru v paměti z Microsoft.AspNetCore.TestHost
balíčku.
Knihovna testů jednotek spustí aplikaci gRPC a služby gRPC se testují pomocí klienta gRPC.
Ukázkový kód obsahuje infrastrukturu, která umožňuje testování integrace:
- Třída
GrpcTestFixture<TStartup>
nakonfiguruje hostitele ASP.NET Core a spustí aplikaci gRPC na testovacím serveru v paměti. - Třída
IntegrationTestBase
je základní typ, ze kterého dědí integrační testy. Obsahuje stav zařízení a rozhraní API pro vytvoření klienta gRPC pro volání aplikace gRPC.
[Fact]
public async Task SayHelloUnaryTest()
{
// Arrange
var client = new Tester.TesterClient(Channel);
// Act
var response = await client.SayHelloUnaryAsync(new HelloRequest { Name = "Joe" });
// Assert
Assert.Equal("Hello Joe", response.Message);
}
Předchozí integrační test:
- Vytvoří klienta gRPC pomocí kanálu, který
IntegrationTestBase
poskytuje . Tento typ je součástí vzorového kódu. - Volá metodu
SayHelloUnary
pomocí klienta gRPC. - Služba vrátí očekávanou zprávu odpovědi.
Vložení napodobených závislostí
Pomocí ConfigureWebHost
zařízení lze přepsat závislosti. Přepsání závislostí je užitečné, když není externí závislost v testovacím prostředí dostupná. Například aplikace, která používá externí platební bránu, by při provádění testů neměla volat externí závislost. Místo toho použijte pro test napodobenou bránu.
public MockedGreeterServiceTests(GrpcTestFixture<Startup> fixture,
ITestOutputHelper outputHelper) : base(fixture, outputHelper)
{
var mockGreeter = new Mock<IGreeter>();
mockGreeter.Setup(
m => m.Greet(It.IsAny<string>())).Returns((string s) =>
{
if (string.IsNullOrEmpty(s))
{
throw new ArgumentException("Name not provided.");
}
return $"Test {s}";
});
Fixture.ConfigureWebHost(builder =>
{
builder.ConfigureServices(
services => services.AddSingleton(mockGreeter.Object));
});
}
[Fact]
public async Task SayHelloUnaryTest_MockGreeter_Success()
{
// Arrange
var client = new Tester.TesterClient(Channel);
// Act
var response = await client.SayHelloUnaryAsync(
new HelloRequest { Name = "Joe" });
// Assert
Assert.Equal("Test Joe", response.Message);
}
Předchozí integrační test:
- V konstruktoru testovací třídy
MockedGreeterServiceTests
:- Napodobení
IGreeter
pomocí Moq. - Přepíše zaregistrovanou
IGreeter
injektáž závislostí pomocíConfigureWebHost
.
- Napodobení
- Volá metodu
SayHelloUnary
pomocí klienta gRPC. - Uplatní očekávanou zprávu odpovědi na základě instance napodobení
IGreeter
.