Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to use WiremockContainerBuilder for grpc using http2 #1239

Closed
GomesNayagam opened this issue Jan 18, 2025 · 16 comments
Closed

How to use WiremockContainerBuilder for grpc using http2 #1239

GomesNayagam opened this issue Jan 18, 2025 · 16 comments
Assignees
Labels

Comments

@GomesNayagam
Copy link

GomesNayagam commented Jan 18, 2025

  1. hellorequest.json in path /mocks/mappings/hellorequest.json
{
  "Request": {
    "Path": {
      "Matchers": [
        {
          "Name": "WildcardMatcher",
          "Pattern": "/grpc/greet.Greeter/SayHello",
          "IgnoreCase": false
        }
      ]
    },
    "Methods": [
      "POST"
    ],
    "Body": {
      "Matcher": {
        "Name": "ProtoBufMatcher",
        "Pattern": "\r\nsyntax = \"proto3\";\r\n\r\npackage greet;\r\n\r\nservice Greeter {\r\n  rpc SayHello (HelloRequest) returns (HelloReply);\r\n}\r\n\r\nmessage HelloRequest {\r\n  string name = 1;\r\n}\r\n\r\nmessage HelloReply {\r\n  string message = 1;\r\n}\r\n",
        "ContentMatcher": {
          "Name": "JsonPartialWildcardMatcher",
          "Pattern": {
            "name": "*"
          },
          "IgnoreCase": false,
          "Regex": false
        },
        "ProtoBufMessageType": "greet.HelloRequest"
      }
    }
  },
  "Response": {
    "BodyAsJson": {
      "message": "hello {{request.BodyAsJson.name}}"
    },
    "UseTransformer": true,
    "TransformerType": "Handlebars",
    "TransformerReplaceNodeOptions": "EvaluateAndTryToConvert",
    "Headers": {
      "Content-Type": "application/grpc"
    },
    "TrailingHeaders": {
      "grpc-status": "0"
    },
    "ProtoDefinition": "\r\nsyntax = \"proto3\";\r\n\r\npackage greet;\r\n\r\nservice Greeter {\r\n  rpc SayHello (HelloRequest) returns (HelloReply);\r\n}\r\n\r\nmessage HelloRequest {\r\n  string name = 1;\r\n}\r\n\r\nmessage HelloReply {\r\n  string message = 1;\r\n}\r\n",
    "ProtoBufMessageType": "greet.HelloReply"
  }
}
  1. code
            var greetContainer = new ContainerBuilder()
                .WithImage("wiremock/wiremock")
                //.WithPortBinding(8080, true)
                .WithBindMount(TestHelper.GetAbsolutePath(@"mocks\greet"), "/home/wiremock")
                .Build();

            await greetContainer.StartAsync();
  1. expected result

container should spin up and ready for testing.

  1. actual result

timeout exception

@StefH StefH self-assigned this Jan 18, 2025
@StefH
Copy link
Collaborator

StefH commented Jan 18, 2025

@GomesNayagam : for better readability, you can use markdown syntax highlighting.

json

``` json
your json here ...
```

And C#

``` c#
your C# code here ...
```

https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks

@StefH
Copy link
Collaborator

StefH commented Jan 18, 2025

To answer your question:
The code you provided is starting WireMock (www.wiremock.org) and not this project.

See this page on how to use it:
https://github.com/WireMock-Net/WireMock.Net/wiki/Using-WireMock.Net.Testcontainers

@StefH StefH closed this as completed Jan 18, 2025
@GomesNayagam
Copy link
Author

GomesNayagam commented Jan 21, 2025

Hi @StefH I tried with new image and container able to up and running but when i query for mapping http://127.0.0.1:49160/app/__admin/mappings

it is throwing. "No matching mapping found"

  1. mapping is same above
  2. unable to find how to set .withhttpversion("2")
  3. used postman to query the method internale error 13 came.
{"Status":"No matching mapping found"}
            var container = new WireMockContainerBuilder()
                .WithAutoRemove(true)
                .WithCleanUp(true)
                .WithMappings(TestHelper.GetAbsolutePath(@"mocks\greet\mappings"))
                .Build();

            await container.StartAsync().ConfigureAwait(false);

@StefH StefH reopened this Jan 21, 2025
@StefH
Copy link
Collaborator

StefH commented Jan 21, 2025

1] I think the URL you need to use is http://127.0.0.1:49160/__admin/mappings (no app)

2] .withhttpversion("2")
For this to work, you need to provide different urls to TestContainers
Can you try

var container = new WireMockContainerBuilder()
                .WithAutoRemove(true)
                .WithCleanUp(true)
                .WithMappings(TestHelper.GetAbsolutePath(@"mocks\greet\mappings"))
                .WithCommand("--Urls http://x.x.x.x:8080 grpc://x.x.x.x:9090").
                .Build();

Where http://x.x.x.x:8080 is the admin url + port to get / post the mappings.
And grpc://x.x.x.x:9090 is the url + port for GRPC.
(Note that you need to provide the correct values for x.x.x.x)

@GomesNayagam
Copy link
Author

GomesNayagam commented Jan 21, 2025

@StefH I tried the above with this code coz i dont want to use any static ip not sure how that works, i am okey to have localhost.

  1. changed port from 8080 to 80 to make the mapping url to work
  2. used 9090 and 9093 as well for grpc it is not working.

POST: grpc://127.0.0.1:53296/grpc
Method: SayHello

Expected: work similar like this article says https://mstack.nl/blogs/wiremock-net-grpc/

            var container = new WireMockContainerBuilder()
                .WithAutoRemove(true)
                .WithCleanUp(true)
                .WithMappings(TestHelper.GetAbsolutePath(@"mocks\greet\mappings"))
                .WithCommand("--Urls http://*:80/  grpc://*:9093/")
                .Build();

Note i tried this preview as well 1.6.12-ci-19580, looks grpc server is not running in this container? correct me if i am wrong.

@GomesNayagam GomesNayagam changed the title How to use wiremock ContainerBuilder for grpc How to use WiremockContainerBuilder for grpc using http2 Jan 22, 2025
@StefH
Copy link
Collaborator

StefH commented Jan 27, 2025

@GomesNayagam
This is indeed not supported yet, I'll take a look if this can be added.

@StefH
Copy link
Collaborator

StefH commented Jan 27, 2025

Can you try this:

var container = new WireMockContainerBuilder()
  .WithCommand("--UseHttp2 true")
  .WithEntrypoint("./wiremock-net", "--Urls", "http://*:80", "grpc://*:9090")
  .WithPortBinding(9090, true)

This will make sure that WireMock.Net inside the container will internally listen to 80 and 9090 and externally will use random ports.

You get get the random ports using:

var httpPort = wireMockContainer.GetMappedPublicPort(80);
var grpcPort = wireMockContainer.GetMappedPublicPort(9090);

Getting the mappings on the httpPort should work.

And calling GRPC method on the grpcPort should also work.

@GomesNayagam
Copy link
Author

@StefH below error

            var wireMockContainer = new WireMockContainerBuilder()
                .WithAutoRemove(true)
                .WithCleanUp(true)
                .WithMappings(TestHelper.GetAbsolutePath(@"mocks\greet\mappings"))
                .WithCommand("--UseHttp2 true")
                .WithEntrypoint("./wiremock-net", "--Urls", "http://*:80", "grpc://*:9090")
                .Build();

            await wireMockContainer.StartAsync();
            var httpPort = wireMockContainer.GetMappedPublicPort(80);
            var grpcPort = wireMockContainer.GetMappedPublicPort(9090);

Error outpu:

  Message: 
System.InvalidOperationException : Exposed port 9090/tcp is not mapped.

  Stack Trace: 
DockerContainer.GetMappedPublicPort(String containerPort) line 248
DockerContainer.GetMappedPublicPort(Int32 containerPort) line 232
GrpcSampleTest.GrpcContainerTest() line 180
--- End of stack trace from previous location ---

@StefH
Copy link
Collaborator

StefH commented Jan 27, 2025

And this?

var wireMockContainer = new WireMockContainerBuilder()
    .WithAutoRemove(true)
    .WithCleanUp(true)
    .WithAdminUserNameAndPassword(adminUsername, adminPassword)
    .WithCommand("--UseHttp2 true")
    .WithCommand("--Urls", "http://*:80 grpc://*:9090")
    .WithPortBinding(9090, true)
    .Build();

@StefH
Copy link
Collaborator

StefH commented Jan 27, 2025

#1246

@StefH
Copy link
Collaborator

StefH commented Jan 27, 2025

Or try preview NuGet version 1.7.1-ci-19645

Which can be used like this:

var wireMockContainer = new WireMockContainerBuilder()
    .WithAutoRemove(true)
    .WithCleanUp(true)
    .WithAdminUserNameAndPassword(adminUsername, adminPassword)
    .AddUrl("http://*:8080")
    .AddUrl("grpc://*:9090")
    .AddUrl("grpc://*:9091")
    .Build();

@StefH StefH added feature and removed question labels Jan 27, 2025
@GomesNayagam
Copy link
Author

@StefH port were running but grpc is not working.

files were in ..\mocks\greet\hellorequest.json

  1. 80 port works and able to get mapping details.

  2. 9090 grpc is nto working with grpc or http protocol. (used postman)

code

            var wireMockContainer = new WireMockContainerBuilder()
                .WithAutoRemove(true)
                .WithCleanUp(true)
                //.WithAdminUserNameAndPassword("gomes", "gomes")
                .WithMappings(TestHelper.GetAbsolutePath(@"mocks\greet\"))
                .WithCommand("--UseHttp2 true")
                .WithEntrypoint("./wiremock-net", "--Urls", "http://*:80", "grpc://*:9090")
                .WithPortBinding(9090, true)
                .Build();

            await wireMockContainer.StartAsync();
            var httpPort = wireMockContainer.GetMappedPublicPort(80);
            var grpcPort = wireMockContainer.GetMappedPublicPort(9090);

error log:

2025-01-27 13:52:02 01/27/2025 21:52:02 [Warn] : HttpStatusCode set to 404 : No matching mapping found
2025-01-27 13:52:02 01/27/2025 21:52:02 [DebugRequestResponse] : Admin[False] {
2025-01-27 13:52:02   "Guid": "9b194fac-6d7d-4b12-bb1e-b69ed16ce855",
2025-01-27 13:52:02   "Request": {
2025-01-27 13:52:02     "ClientIP": "172.17.0.1",
2025-01-27 13:52:02     "DateTime": "2025-01-27T21:52:02.4351112Z",
2025-01-27 13:52:02     "Path": "/grpc/greet.Greeter/SayHello",
2025-01-27 13:52:02     "AbsolutePath": "/grpc/greet.Greeter/SayHello",
2025-01-27 13:52:02     "Url": "http://127.0.0.1:59558/grpc/greet.Greeter/SayHello",
2025-01-27 13:52:02     "AbsoluteUrl": "http://127.0.0.1:59558/grpc/greet.Greeter/SayHello",
2025-01-27 13:52:02     "ProxyUrl": null,
2025-01-27 13:52:02     "Query": {},
2025-01-27 13:52:02     "Method": "POST",
2025-01-27 13:52:02     "HttpVersion": "2",
2025-01-27 13:52:02     "Headers": {
2025-01-27 13:52:02       "Host": [
2025-01-27 13:52:02         "127.0.0.1:59558"
2025-01-27 13:52:02       ],
2025-01-27 13:52:02       "User-Agent": [
2025-01-27 13:52:02         "grpc-node-js/1.11.0-postman.1"
2025-01-27 13:52:02       ],
2025-01-27 13:52:02       "Accept-Encoding": [
2025-01-27 13:52:02         "identity"
2025-01-27 13:52:02       ],
2025-01-27 13:52:02       "Content-Type": [
2025-01-27 13:52:02         "application/grpc"
2025-01-27 13:52:02       ],
2025-01-27 13:52:02       "Grpc-Accept-Encoding": [
2025-01-27 13:52:02         "identity,deflate,gzip"
2025-01-27 13:52:02       ],
2025-01-27 13:52:02       "TE": [
2025-01-27 13:52:02         "trailers"
2025-01-27 13:52:02       ]
2025-01-27 13:52:02     },
2025-01-27 13:52:02     "Cookies": {},
2025-01-27 13:52:02     "Body": "\u0000\u0000\u0000\u0000\u001d\n\u001baute deserunt voluptate qui",
2025-01-27 13:52:02     "BodyAsJson": null,
2025-01-27 13:52:02     "BodyAsBytes": null,
2025-01-27 13:52:02     "BodyEncoding": {
2025-01-27 13:52:02       "CodePage": 65001,
2025-01-27 13:52:02       "EncodingName": "Unicode (UTF-8)",
2025-01-27 13:52:02       "WebName": "utf-8"
2025-01-27 13:52:02     },
2025-01-27 13:52:02     "DetectedBodyType": "String",
2025-01-27 13:52:02     "DetectedBodyTypeFromContentType": "ProtoBuf"
2025-01-27 13:52:02   },
2025-01-27 13:52:02   "Response": {
2025-01-27 13:52:02     "StatusCode": 404,
2025-01-27 13:52:02     "Headers": {
2025-01-27 13:52:02       "Content-Type": [
2025-01-27 13:52:02         "application/json"
2025-01-27 13:52:02       ]
2025-01-27 13:52:02     },
2025-01-27 13:52:02     "BodyDestination": null,
2025-01-27 13:52:02     "Body": null,
2025-01-27 13:52:02     "BodyAsJson": {
2025-01-27 13:52:02       "Guid": null,
2025-01-27 13:52:02       "Status": "No matching mapping found",
2025-01-27 13:52:02       "Error": null
2025-01-27 13:52:02     },
2025-01-27 13:52:02     "BodyAsBytes": null,
2025-01-27 13:52:02     "BodyAsFile": null,
2025-01-27 13:52:02     "BodyAsFileIsCached": null,
2025-01-27 13:52:02     "BodyOriginal": null,
2025-01-27 13:52:02     "BodyEncoding": null,
2025-01-27 13:52:02     "DetectedBodyType": 2,
2025-01-27 13:52:02     "DetectedBodyTypeFromContentType": null,
2025-01-27 13:52:02     "FaultType": null,
2025-01-27 13:52:02     "FaultPercentage": null
2025-01-27 13:52:02   },
2025-01-27 13:52:02   "MappingGuid": null,
2025-01-27 13:52:02   "MappingTitle": null,
2025-01-27 13:52:02   "RequestMatchResult": null,
2025-01-27 13:52:02   "PartialMappingGuid": "0a9b40ab-a6e5-42fd-ae4a-705df2f1023f",
2025-01-27 13:52:02   "PartialMappingTitle": null,
2025-01-27 13:52:02   "PartialRequestMatchResult": {
2025-01-27 13:52:02     "TotalScore": 2.0,
2025-01-27 13:52:02     "TotalNumber": 3,
2025-01-27 13:52:02     "IsPerfectMatch": false,
2025-01-27 13:52:02     "AverageTotalScore": 0.6666666666666666,
2025-01-27 13:52:02     "MatchDetails": [
2025-01-27 13:52:02       {
2025-01-27 13:52:02         "Name": "PathMatcher",
2025-01-27 13:52:02         "Score": 1.0
2025-01-27 13:52:02       },
2025-01-27 13:52:02       {
2025-01-27 13:52:02         "Name": "MethodMatcher",
2025-01-27 13:52:02         "Score": 1.0
2025-01-27 13:52:02       },
2025-01-27 13:52:02       {
2025-01-27 13:52:02         "Name": "BodyMatcher",
2025-01-27 13:52:02         "Score": 0.0
2025-01-27 13:52:02       }
2025-01-27 13:52:02     ]
2025-01-27 13:52:02   }
2025-01-27 13:52:02 }

@StefH
Copy link
Collaborator

StefH commented Jan 28, 2025

@GomesNayagam
Copy link
Author

GomesNayagam commented Jan 28, 2025

@StefH this works, also luv to see the container works like static server, to add protodefinition and refer it from mappings. like

"ProtoDefinition": "my-greeter"

server.AddProtoDefinition("my-greeter", ReadProtoFile("greet.proto"));

Another request, can you remove this file and related code base as i provided this for e.g and i don't want to be in trouble from my company or atleast remove the line# 27 to 37 and update with some dummy value.

https://github.com/WireMock-Net/WireMock.Net/blob/master/test/WireMock.Net.Tests/Grpc/policy.proto#L27C2-L37C24

@StefH
Copy link
Collaborator

StefH commented Jan 29, 2025

@GomesNayagam

  1. Can you create a new issue for "add protodefinition and refer it from mapping"
  2. I've updated example + unit tests

@GomesNayagam
Copy link
Author

@StefH appreciate it here is the feature request #1249 and let me know when the above tested pre release will be in main release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants