Prueba de servicios gRPC en ASP.NET Core
Las pruebas son un aspecto importante de la creación de software estable y fácil de mantener. En este artículo se describe cómo probar servicios gRPC en ASP.NET Core.
Hay tres enfoques comunes para probar los servicios gRPC:
- Pruebas unitarias: pruebe los servicios gRPC directamente desde una biblioteca de pruebas unitarias.
- Prueba de integración: la aplicación gRPC se hospeda en TestServer, un servidor de pruebas en memoria del paquete
Microsoft.AspNetCore.TestHost
. Los servicios gRPC se prueban llamándolos mediante un cliente gRPC desde una biblioteca de pruebas unitarias. - Pruebas manuales: pruebe servidores gRPC con llamadas ad hoc. Para obtener información sobre cómo usar la línea de comandos y las herramientas de interfaz de usuario con servicios gRPC, vea Comprobación de servicios gRPC con gRPCurl y gRPCui en ASP.NET Core.
En las pruebas unitarias, solo está implicado el servicio gRPC. Las dependencias que se insertan en el servicio deben simularse. En las pruebas de integración, el servicio gRPC y su infraestructura auxiliar forman parte de la prueba. Esto incluye el inicio de la aplicación, la inserción de dependencias, el enrutamiento, la autenticación y la autorización.
Ejemplo de servicio que se puede probar
Para demostrar las pruebas de servicio, revise el siguiente servicio en la aplicación de ejemplo.
Vea o descargue el código de ejemplo (cómo descargarlo)
TesterService
devuelve saludos mediante cuatro tipos de método 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) });
}
}
}
El servicio gRPC anterior:
- Sigue el Principio de dependencias explícitas.
- Espera la inserción de dependencias (DI) para ofrecer una instancia de
IGreeter
. - Se puede probar con un servicio
IGreeter
ficticio con el uso de un marco de objeto ficticio, como Moq. Un objeto ficticio es un objeto fabricado con un conjunto predeterminado de comportamientos de propiedades y métodos utilizados para las pruebas. Para más información, vea Pruebas de integración en ASP.NET Core.
Servicios gRPC de prueba unitaria
Una biblioteca de pruebas unitarias puede probar directamente los servicios gRPC llamando a sus métodos. Las pruebas unitarias prueban un servicio gRPC de forma aislada.
[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);
}
La prueba unitaria anterior:
- Simula
IGreeter
mediante Moq. - Ejecuta el método
SayHelloUnary
con un mensaje de solicitud y un elementoServerCallContext
. Todos los métodos de servicio tienen un argumentoServerCallContext
. En esta prueba, el tipo se proporciona mediante el método auxiliarTestServerCallContext.Create()
. Este método auxiliar se incluye en el código de ejemplo. - Realiza aserciones:
- Comprueba que el nombre de la solicitud se pasa a
IGreeter
. - El servicio devuelve el mensaje de respuesta esperado.
- Comprueba que el nombre de la solicitud se pasa a
Prueba unitaria HttpContext
en métodos gRPC
Los métodos gRPC pueden acceder a la clase HttpContext de una solicitud mediante el método de extensión ServerCallContext.GetHttpContext
. Para realizar una prueba unitaria de un método que usa HttpContext
, el contexto debe configurarse en la configuración de la prueba. Si HttpContext no está configurado, GetHttpContext
devuelve null
.
Para configurar un parámetro HttpContext
durante la configuración de la prueba, cree una instancia y agrégrela a la colección ServerCallContext.UserState
mediante la clave __HttpContext
.
var httpContext = new DefaultHttpContext();
var serverCallContext = TestServerCallContext.Create();
serverCallContext.UserState["__HttpContext"] = httpContext;
Ejecute métodos de servicio con este contexto de llamada para usar la instancia de HttpContext
configurada.
Servicios gRPC de pruebas de integración
Las pruebas de integración evalúan los componentes de una aplicación en un nivel más amplio que las pruebas unitarias. La aplicación gRPC se hospeda en TestServer, un servidor de pruebas en memoria del paquete Microsoft.AspNetCore.TestHost
.
Una biblioteca de pruebas unitarias inicia la aplicación gRPC y, a continuación, los servicios gRPC se prueban mediante el cliente gRPC.
El código de ejemplo contiene la infraestructura para que las pruebas de integración puedan realizarse:
- La clase
GrpcTestFixture<TStartup>
configura el host de ASP.NET Core e inicia la aplicación gRPC en un servidor de prueba en memoria. - La clase
IntegrationTestBase
es el tipo base del que heredan las pruebas de integración. Contiene el estado del accesorio y las API para crear un cliente gRPC para llamar a la aplicación 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);
}
La prueba de integración anterior:
- Crea un cliente gRPC mediante el canal proporcionado por
IntegrationTestBase
. Este tipo se incluye en el código de ejemplo. - Llama al método
SayHelloUnary
mediante el cliente gRPC. - Declara que el servicio devuelve el mensaje de respuesta esperado.
Inserción de dependencias simuladas
Use ConfigureWebHost
en el accesorio para invalidar las dependencias. Invalidar dependencias es útil cuando una dependencia externa no está disponible en el entorno de prueba. Por ejemplo, una aplicación que usa una puerta de enlace de pago externa no debe llamar a la dependencia externa al ejecutar pruebas. En su lugar, use una puerta de enlace simulada para la prueba.
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);
}
La prueba de integración anterior:
- En el constructor (
MockedGreeterServiceTests
) de la clase de prueba:- Simula
IGreeter
mediante Moq. - Invalida el elemento
IGreeter
registrado con la inserción de dependencias medianteConfigureWebHost
.
- Simula
- Llama al método
SayHelloUnary
mediante el cliente gRPC. - Declara el mensaje de respuesta esperado basado en la instancia
IGreeter
simulada.
Recursos adicionales
Comentarios
https://aka.ms/ContentUserFeedback.
Próximamente: A lo largo de 2024 iremos eliminando gradualmente GitHub Issues como mecanismo de comentarios sobre el contenido y lo sustituiremos por un nuevo sistema de comentarios. Para más información, vea:Enviar y ver comentarios de