Nguon: Microsoft Learn · .NET 8.0

Mock gRPC client trong tests (kiểm thử)

Nguồn: Mock gRPC client in tests

Bởi James Newton-King

Kiểm thử là một khía cạnh quan trọng để xây dựng phần mềm ổn định và dễ bảo trì. Một phần của việc viết các test chất lượng cao là loại bỏ các external dependencies (phụ thuộc bên ngoài). Bài viết này thảo luận về việc sử dụng mock gRPC client trong tests để loại bỏ các lệnh gọi gRPC đến server bên ngoài.

Ví dụ ứng dụng client có thể kiểm thử

Để minh họa các test ứng dụng client, hãy xem xét type sau trong ứng dụng mẫu.

Xem hoặc tải xuống mã mẫu

Worker là một BackgroundService thực hiện các lệnh gọi đến gRPC server.

csharp
public class Worker : BackgroundService
{
    private readonly Tester.TesterClient _client;
    private readonly IGreetRepository _greetRepository;

    public Worker(Tester.TesterClient client, IGreetRepository greetRepository)
    {
        _client = client;
        _greetRepository = greetRepository;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        var count = 0;
        while (!stoppingToken.IsCancellationRequested)
        {
            count++;

            var reply = await _client.SayHelloUnaryAsync(
                new HelloRequest { Name = $"Worker {count}" });

            _greetRepository.SaveGreeting(reply.Message);

            await Task.Delay(1000, stoppingToken);
        }
    }
}

Type trên:

Để biết thêm thông tin về các C# asset được tự động tạo bởi Grpc.Tools, xem gRPC services with C#: Generated C# assets.

Mock một gRPC client

gRPC client là các concrete client type được tạo từ các file .proto. gRPC client cụ thể có các method dịch sang gRPC service trong file .proto. Ví dụ: một service có tên Greeter tạo ra type GreeterClient với các method để gọi service.

Mocking framework có thể mock một gRPC client type. Khi một mocked client được truyền vào type, test sử dụng method đã được mock thay vì gửi lệnh gọi gRPC đến server.

csharp
[Fact]
public async Task Greeting_Success_RepositoryCalled()
{
    // Arrange (chuẩn bị)
    var mockRepository = new Mock<IGreetRepository>();

    var mockCall = CallHelpers.CreateAsyncUnaryCall(new HelloReply { Message = "Test" });
    var mockClient = new Mock<Tester.TesterClient>();
    mockClient
        .Setup(m => m.SayHelloUnaryAsync(
            It.IsAny<HelloRequest>(), null, null, CancellationToken.None))
        .Returns(mockCall);

    var worker = new Worker(mockClient.Object, mockRepository.Object);

    // Act (thực thi)
    await worker.StartAsync(CancellationToken.None);

    // Assert (kiểm tra)
    mockRepository.Verify(v => v.SaveGreeting("Test"));
}

Unit test trên: