Testare i servizi gRPC in ASP.NET Core
Nota
Questa non è la versione più recente di questo articolo. Per la versione corrente, vedere la versione .NET 9 di questo articolo.
Avviso
Questa versione di ASP.NET Core non è più supportata. Per altre informazioni, vedere i criteri di supporto di .NET e .NET Core. Per la versione corrente, vedere la versione .NET 9 di questo articolo.
Importante
Queste informazioni si riferiscono a un prodotto non definitive che può essere modificato in modo sostanziale prima che venga rilasciato commercialmente. Microsoft non riconosce alcuna garanzia, espressa o implicita, in merito alle informazioni qui fornite.
Per la versione corrente, vedere la versione .NET 9 di questo articolo.
Il test è un aspetto importante della creazione di software stabile e gestibile. Questo articolo illustra come testare i servizi ASP.NET Core gRPC.
Esistono tre approcci comuni per testare i servizi gRPC:
- Unit test: testare i servizi gRPC direttamente da una libreria di unit test.
- Test di integrazione: l'app gRPC è ospitata in TestServer, un server di test in memoria dal
Microsoft.AspNetCore.TestHost
pacchetto. I servizi gRPC vengono testati chiamandoli usando un client gRPC da una libreria di unit test. - Test manuali: testare i server gRPC con chiamate ad hoc. Per informazioni su come usare gli strumenti della riga di comando e dell'interfaccia utente con i servizi gRPC, vedere Testare i servizi gRPC con gRPCurl e gRPCui in ASP.NET Core.
Negli unit test è coinvolto solo il servizio gRPC. Le dipendenze inserite nel servizio devono essere fittizie. Nei test di integrazione, il servizio gRPC e l'infrastruttura ausiliaria fanno parte del test. Sono inclusi l'avvio dell'app, l'inserimento delle dipendenze, il routing e l'autenticazione e l'autorizzazione.
Esempio di servizio testabile
Per illustrare i test del servizio, esaminare il servizio seguente nell'app di esempio.
Visualizzare o scaricare il codice di esempio (procedura per il download)
Restituisce TesterService
i messaggi di saluto usando i quattro tipi di metodo di 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) });
}
}
}
Servizio gRPC precedente:
- Segue il principio delle dipendenze esplicite.
- Si aspetta che l'inserimento delle dipendenze fornisca un'istanza di
IGreeter
. - Può essere testato con un servizio
IGreeter
fittizio tramite il framework di un oggetto fittizio, ad esempio Moq. Un oggetto fittizio è un oggetto creato con un set predeterminato di comportamenti di proprietà e metodi usati per il testing. Per altre informazioni, vedere Test di integrazione in ASP.NET Core.
Servizi gRPC di unit test
Una libreria di unit test può testare direttamente i servizi gRPC chiamando i relativi metodi. Gli unit test testano un servizio gRPC in isolamento.
[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);
}
Lo unit test precedente:
- Simula l'uso di
IGreeter
Moq. - Esegue il
SayHelloUnary
metodo con un messaggio di richiesta e un oggettoServerCallContext
. Tutti i metodi del servizio hanno unServerCallContext
argomento . In questo test il tipo viene fornito usando ilTestServerCallContext.Create()
metodo helper. Questo metodo helper è incluso nel codice di esempio. - Crea asserzioni:
- Verifica che il nome della richiesta venga passato a
IGreeter
. - Il servizio restituisce il messaggio di risposta previsto.
- Verifica che il nome della richiesta venga passato a
Unit test HttpContext
nei metodi gRPC
I metodi gRPC possono accedere a una richiesta HttpContext usando il ServerCallContext.GetHttpContext
metodo di estensione. Per eseguire unit test di un metodo che usa HttpContext
, il contesto deve essere configurato nell'installazione di test. Se HttpContext non è configurato, GetHttpContext
restituisce null
.
Per configurare un oggetto HttpContext
durante l'installazione dei test, creare una nuova istanza e aggiungerla alla ServerCallContext.UserState
raccolta usando la __HttpContext
chiave .
var httpContext = new DefaultHttpContext();
var serverCallContext = TestServerCallContext.Create();
serverCallContext.UserState["__HttpContext"] = httpContext;
Eseguire i metodi del servizio con questo contesto di chiamata per usare l'istanza configurata HttpContext
.
Servizi GRPC di test di integrazione
I test di integrazione valutano i componenti di un'app in un livello più ampio rispetto agli unit test. L'app gRPC è ospitata in TestServer, un server di test in memoria dal Microsoft.AspNetCore.TestHost
pacchetto.
Una libreria di unit test avvia l'app gRPC e quindi i servizi gRPC vengono testati usando il client gRPC.
Il codice di esempio contiene l'infrastruttura per rendere possibile il test di integrazione:
- La
GrpcTestFixture<TStartup>
classe configura l'host ASP.NET Core e avvia l'app gRPC in un server di test in memoria. - La
IntegrationTestBase
classe è il tipo di base da cui ereditano i test di integrazione. Contiene lo stato e le API della fixture per la creazione di un client gRPC per chiamare l'app 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);
}
Test di integrazione precedente:
- Crea un client gRPC usando il canale fornito da
IntegrationTestBase
. Questo tipo è incluso nel codice di esempio. - Chiama il
SayHelloUnary
metodo usando il client gRPC. - Asserisce che il servizio restituisce il messaggio di risposta previsto.
Inserire dipendenze fittizie
Usare ConfigureWebHost
nella fixture per eseguire l'override delle dipendenze. L'override delle dipendenze è utile quando una dipendenza esterna non è disponibile nell'ambiente di test. Ad esempio, un'app che usa un gateway di pagamento esterno non deve chiamare la dipendenza esterna durante l'esecuzione dei test. Usare invece un gateway fittizio per il test.
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);
}
Test di integrazione precedente:
- Nel costruttore della classe di test (
MockedGreeterServiceTests
):- Simula l'uso di
IGreeter
Moq. - Esegue l'override dell'oggetto registrato con l'inserimento
IGreeter
delle dipendenze tramiteConfigureWebHost
.
- Simula l'uso di
- Chiama il
SayHelloUnary
metodo usando il client gRPC. - Asserisce il messaggio di risposta previsto in base all'istanza fittizia
IGreeter
.