Tester les services gRPC dans ASP.NET Core
Remarque
Ceci n’est pas la dernière version de cet article. Pour la version actuelle, consultez la version .NET 9 de cet article.
Avertissement
Cette version d’ASP.NET Core n’est plus prise en charge. Pour plus d’informations, consultez la stratégie de support .NET et .NET Core. Pour la version actuelle, consultez la version .NET 9 de cet article.
Important
Ces informations portent sur la préversion du produit, qui est susceptible d’être en grande partie modifié avant sa commercialisation. Microsoft n’offre aucune garantie, expresse ou implicite, concernant les informations fournies ici.
Pour la version actuelle, consultez la version .NET 9 de cet article.
Par : James Newton-King
Les tests sont un aspect important de la création de logiciels stables et maintenables. Cet article explique comment tester les services gRPC ASP.NET Core.
Il existe trois approches courantes pour tester les services gRPC :
- Test unitaire : testez les services gRPC directement à partir d’une bibliothèque de tests unitaires.
- Test d’intégration : l’application gRPC est hébergée dans TestServer, un serveur de test en mémoire à partir du package
Microsoft.AspNetCore.TestHost
. Les services gRPC sont testés en les appelant à l’aide d’un client gRPC à partir d’une bibliothèque de test unitaire. - Test manuel : testez les serveurs gRPC avec des appels ad hoc. Pour plus d’informations sur l’utilisation des outils de ligne de commande et d’interface utilisateur avec les services gRPC, consultez Tester les services gRPCurl avec gRPCui dans ASP.NET Core.
Dans les tests unitaires, seul le service gRPC est impliqué. Les dépendances injectées dans le service doivent être moquées. Dans les tests d’intégration, le service gRPC et son infrastructure auxiliaire font partie du test. Cela inclut le démarrage de l’application, l’injection de dépendances, le routage et l’authentification et l’autorisation.
Exemple de service testable
Pour illustrer les tests de service, passez en revue le service suivant dans l’échantillon d’application.
Affichez ou téléchargez l’exemple de code (procédure de téléchargement)
Le TesterService
retourne les salutations avec les quatre types de méthode de 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) });
}
}
}
Le service gRPC précédent :
- Suit le Principe des dépendances explicites.
- Attend que l’injection de dépendance fournisse une instance de
IGreeter
. - Peut être testé avec un service
IGreeter
fictif au moyen d’un framework d’objets fictifs, tel que Moq. Un objet fictif est un objet fabriqué avec un ensemble prédéterminé de comportements de propriété et de méthode utilisés pour les tests. Pour plus d’informations, consultez Tests d’intégration dans ASP.NET Core.
Services gRPC de test unitaire
Une bibliothèque de tests unitaires peut tester directement les services gRPC en appelant ses méthodes. Les tests unitaires testent un service gRPC isolé.
[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);
}
Le test unitaire précédent :
IGreeter
fictif à l’aide de Moq.- Exécute la méthode
SayHelloUnary
avec un message de requête et unServerCallContext
. Toutes les méthodes de service ont un argumentServerCallContext
. Dans ce test, le type est fourni à l’aide de la méthode d’assistanceTestServerCallContext.Create()
. Cette méthode d’assistance est incluse dans l’échantillon de code. - Effectue des assertions :
- Vérifie que le nom de la requête est passé à
IGreeter
. - Le service retourne le message de réponse attendu.
- Vérifie que le nom de la requête est passé à
Test unitaire HttpContext
dans les méthodes gRPC
Les méthodes gRPC peuvent accéder aux requêtes HttpContext à l’aide de la méthode d’extension ServerCallContext.GetHttpContext
. Pour tester unitairement une méthode qui utilise HttpContext
, le contexte doit être configuré dans le programme d’installation de test. Si HttpContext n’est pas configuré, GetHttpContext
retourne null
.
Pour configurer un HttpContext
pendant la configuration du test, créez un instance et ajoutez-la à la collection ServerCallContext.UserState
à l’aide de la clé __HttpContext
.
var httpContext = new DefaultHttpContext();
var serverCallContext = TestServerCallContext.Create();
serverCallContext.UserState["__HttpContext"] = httpContext;
Exécutez des méthodes de service avec ce contexte d’appel pour utiliser l’instance HttpContext
configurée.
Services gRPC de test d’intégration
Les tests d’intégration évaluent les composants d’une application à un niveau plus large que les tests unitaires. L’application gRPC est hébergée dans TestServer, un serveur de test en mémoire à partir du package Microsoft.AspNetCore.TestHost
.
Une bibliothèque de tests unitaires démarre l’application gRPC, puis les services gRPC sont testés à l’aide du client gRPC.
L’échantillon de code contient l’infrastructure pour rendre possible le test d’intégration :
- La classe
GrpcTestFixture<TStartup>
configure l’hôte ASP.NET Core et démarre l’application gRPC dans un serveur de test en mémoire. - La classe
IntegrationTestBase
est le type de base dont héritent les tests d’intégration. Il contient l’état de la fixation et les API permettant de créer un client gRPC pour appeler l’application 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);
}
Le test d’intégration précédent :
- Crée un client gRPC à l’aide du canal fourni par
IntegrationTestBase
. Ce type est inclus dans l’échantillon de code. - Appelle la méthode
SayHelloUnary
à l’aide du client gRPC. - Affirme que le service retourne le message de réponse attendu.
Injecter des dépendances fictives
Utilisez ConfigureWebHost
sur la fixture pour remplacer les dépendances. Le remplacement de dépendances est utile lorsqu’une dépendance externe n’est pas disponible dans l’environnement de test. Par exemple, une application qui utilise une passerelle de paiement externe ne doit pas appeler la dépendance externe lors de l’exécution de tests. Utilisez plutôt une passerelle factice pour le 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);
}
Le test d’intégration précédent :
- Dans le constructeur de la classe de test (
MockedGreeterServiceTests
) :IGreeter
fictif à l’aide de Moq.- Remplace le
IGreeter
inscrit avec l’injection de dépendances à l’aide deConfigureWebHost
.
- Appelle la méthode
SayHelloUnary
à l’aide du client gRPC. - Assertion du message de réponse attendu en fonction de l’instance fictive
IGreeter
.