WireMock-Net / WireMock.Net

WireMock.Net is a flexible product for stubbing and mocking web HTTP responses using advanced request matching and response templating. Based on the functionality from http://WireMock.org, but extended with more functionality.
Apache License 2.0
1.35k stars 197 forks source link

ProtoBufMatcher import in proto not working #1079

Closed vgoranski closed 3 months ago

vgoranski commented 3 months ago

Describe the bug

I'm not sure if it's a bug or more of a feature request, but it seems that the current implmentation of ProtoBufMatcher is not supporting imports in proto.

Expected behavior:

Imports in proto work.

Test to reproduce

[Fact]
public async Task WireMockServer_WithBodyAsProtoBuf_InlineProtoDefinition_UsingGrpcGeneratedClient_UsingProtoImport()
{
    const string protoDefinition = """

                                   syntax = "proto3";

                                   import "google/protobuf/wrappers.proto";

                                   package greet;

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

                                   message HelloRequest {
                                       string name = 1;
                                       google.protobuf.StringValue last_name = 2;
                                   }

                                   message HelloReply {
                                       string message = 1;
                                       google.protobuf.StringValue other = 2;
                                   }
                                   """;

    // Arrange
    using var server = WireMockServer.Start(useHttp2: true);

    var jsonMatcher = new JsonMatcher(new { name = "John" });

    server
        .Given(Request.Create()
                      .UsingPost()
                      .WithPath("/greet.Greeter/SayHello")
                      .WithBodyAsProtoBuf(protoDefinition, "greet.HelloRequest", jsonMatcher)
        )
        .RespondWith(Response.Create()
                             .WithHeader("Content-Type", "application/grpc")
                             .WithTrailingHeader("grpc-status", "0")
                             .WithBodyAsProtoBuf(protoDefinition, "greet.HelloReply",
                                 new
                                 {
                                     message = "hello John {{request.method}}",
                                     other = "other message"
                                 }
                             )
                             .WithTransformer()
        );

    // Act
    var channel = GrpcChannel.ForAddress(server.Url!);

    var client = new Greeter.GreeterClient(channel);

    var reply = await client.SayHelloAsync(new HelloRequest { Name = "John", LastName = "Doe" });

    // Assert
    reply.Message.Should().Be("hello John POST");
    reply.Other.Should().Be("other message");

    server.Stop();
}
StefH commented 3 months ago

Imports should work, see default example proto definition here: https://protobuf.heyenrath.nl/

I think that the JsonMatcher will not match, I think in that case you need a https://github.com/WireMock-Net/WireMock.Net/wiki/Request-Matching-JsonPartialMatcher

vgoranski commented 3 months ago

Yes, imports actually work. In my example above the problem was eventually the JsonMatcher.

I also noticed that in case when none of the types are used from the import, then there will be an error. But usually, if you use an import you should use the types from it, so I guess it's not that big of a deal.

[Fact]
public async Task WireMockServer_WithBodyAsProtoBuf_InlineProtoDefinition_UsingGrpcGeneratedClient_UsingProtoImport()
{
    const string protoDefinition = """
                                   syntax = "proto3";

                                   import "google/protobuf/wrappers.proto";

                                   package greet;

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

                                   message HelloRequest {
                                       string name = 1;
                                   }

                                   message HelloReply {
                                       string message = 1;
                                   }
                                   """;

    // Arrange
    using var server = WireMockServer.Start(useHttp2: true);

    server
        .Given(Request.Create()
                      .UsingPost()
                      .WithPath("/greet.Greeter/SayHello")
                      .WithBodyAsProtoBuf(protoDefinition, "greet.HelloRequest")
        )
        .RespondWith(Response.Create()
                             .WithHeader("Content-Type", "application/grpc")
                             .WithTrailingHeader("grpc-status", "0")
                             .WithBodyAsProtoBuf(protoDefinition, "greet.HelloReply",
                                 new
                                 {
                                     message = "hello John {{request.method}}"
                                 }
                             )
                             .WithTransformer()
        );

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

    var reply = await client.SayHelloAsync(new HelloRequest { Name = "John" });

    // Assert
    reply.Message.Should().Be("hello John POST");

    server.Stop();
}

If you remove the import form this example, everything will work fine.

StefH commented 3 months ago

also noticed that in case when none of the types are used from the import, then there will be an error.

This is very strange, I need to check that. can you maybe create a issue here : https://github.com/StefH/ProtoBufJsonConverter ?

StefH commented 3 months ago

Closing this one...