Skip to content

Repository files navigation

WireMock.Net.Google.Protobuf

GitHub stars License: MIT

Link to NuGet: https://www.nuget.org/packages/WireMock.Grpc.Protobuf

Statically typed gRPC mocking for WireMock.Net using generated Google.Protobuf contracts.

Request.Create()
    .WithBodyAsGoogleProtobuf(new HelloRequest { Name = "Stepan" });

Response.Create()
    .WithBodyAsGoogleProtobuf(
        new HelloReply { Message = "Hello, Stepan!" });

No ProtoDefinition, message type strings, JSON conversion, or manually constructed binary payloads.

Why?

The standard WireMock.Net protobuf integration requires loading .proto definitions and referring to protobuf message types separately from your generated C# contracts.

This package uses the generated IMessage<T> types you already have to write less configuration and do no duplicated schema setup:

  • compile-time type safety;
  • native Google.Protobuf serialization;
  • exact-message and predicate request matching;

When a contract changes, outdated mocks stop compiling instead of failing at runtime.

Installation

dotnet add package WireMock.Grpc.Protobuf

The package targets .NET Standard 2.0 and .NET 8.

Message Matching

Assuming you have some greet.proto file that generates HelloRequest, HelloReply, and Greeter.GreeterClient for instance:

syntax = "proto3";

option csharp_namespace = "Greeting.Contracts";

package greet;

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply);
}

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}

And assuming you also have the required packages added with protobuf compilation settings to your test project:

<Project Sdk="Microsoft.NET.Sdk">
    <ItemGroup>
        <PackageReference Include="WireMock.Net" Version="2.13.0" />
        <PackageReference Include="WireMock.Grpc.Protobuf" Version="1.0.0" />
        <PackageReference Include="Grpc.Net.Client" Version="2.80.0" />
        <PackageReference Include="Grpc.Core" Version="2.46.6"/>
        <PackageReference Include="Grpc.Tools" Version="2.82.0">
            <PrivateAssets>all</PrivateAssets>
            <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
        </PackageReference>
    </ItemGroup>

    <ItemGroup>
        <Protobuf Include=".\test.proto" GrpcServices="Client" />
    </ItemGroup>
</Project>

Start WireMock.Net with HTTP/2 enabled and configure the expected request and response using the WithBodyAsGoogleProtobuf extension methods:

using Greeting.Contracts;
using Grpc.Net.Client;
using WireMock.Net.Google.Protobuf.Request;
using WireMock.Net.Google.Protobuf.Response;
using WireMock.RequestBuilders;
using WireMock.ResponseBuilders;
using WireMock.Server;
using WireMock.Settings;

using var server = WireMockServer.Start(
    new WireMockServerSettings
    {
        UseHttp2 = true
    });

var request = new HelloRequest
{
    Name = "Stepan"
};

var expectedResponse = new HelloReply
{
    Message = "Hello, Stepan!"
};

server
    .Given(
        Request.Create()
            .UsingPost()
            .WithHttpVersion("2")
            .WithPath("/greet.Greeter/SayHello")
            .WithBodyAsGoogleProtobuf(request))
    .RespondWith(
        Response.Create()
            .WithHeader("Content-Type", "application/grpc")
            .WithTrailingHeader("grpc-status", "0")
            .WithBodyAsGoogleProtobuf(expectedResponse));

using var channel = GrpcChannel.ForAddress(server.Url!);
var client = new Greeter.GreeterClient(channel);

var actualResponse = await client.SayHelloAsync(request);

Assert.Equal(expectedResponse, actualResponse);

Predicate Matching

Match only the fields relevant to your test:

Request.Create()
    .WithBodyAsGoogleProtobuf<HelloRequest>(
        request =>
            request.Name.StartsWith("Step") &&
            request.Name.Length >= 5);

This keeps request matching strongly typed without comparing the entire protobuf message.

Important

Do not call WithTransformer() after WithBodyAsGoogleProtobuf(). The response is already a binary gRPC frame, and text transformation may corrupt it.

WireMock.Net must also run with HTTP/2 enabled:

new WireMockServerSettings
{
    UseHttp2 = true
};

License

Distributed under the MIT License.

About

Statically typed gRPC mocking for WireMock.Net using generated Google.Protobuf contracts

Resources

Stars

9 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages