{"id":13629470,"url":"https://github.com/cezarypiatek/GRPC-Mock-Server","last_synced_at":"2025-04-17T09:34:05.814Z","repository":{"id":166171286,"uuid":"641614792","full_name":"cezarypiatek/GRPC-Mock-Server","owner":"cezarypiatek","description":"Super fast, platform independent, standalone component for mocking GRPC services using WireMock.NET stubbing engine","archived":false,"fork":false,"pushed_at":"2023-10-09T21:03:40.000Z","size":93,"stargazers_count":31,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-08-01T22:43:43.255Z","etag":null,"topics":["csharp-sourcegenerator","grpc","http","mock-server","mocking","stubbing"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cezarypiatek.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2023-05-16T21:04:02.000Z","updated_at":"2024-07-30T02:49:06.000Z","dependencies_parsed_at":null,"dependency_job_id":"5f078dd4-fbdf-4dce-84ed-ecf3d07beb54","html_url":"https://github.com/cezarypiatek/GRPC-Mock-Server","commit_stats":null,"previous_names":[],"tags_count":26,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cezarypiatek%2FGRPC-Mock-Server","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cezarypiatek%2FGRPC-Mock-Server/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cezarypiatek%2FGRPC-Mock-Server/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cezarypiatek%2FGRPC-Mock-Server/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cezarypiatek","download_url":"https://codeload.github.com/cezarypiatek/GRPC-Mock-Server/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223751145,"owners_count":17196579,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["csharp-sourcegenerator","grpc","http","mock-server","mocking","stubbing"],"created_at":"2024-08-01T22:01:11.477Z","updated_at":"2024-11-08T20:31:00.916Z","avatar_url":"https://github.com/cezarypiatek.png","language":"C#","funding_links":[],"categories":["Contributors Welcome for those","Source Generators"],"sub_categories":["1. [ThisAssembly](https://ignatandrei.github.io/RSCG_Examples/v2/docs/ThisAssembly) , in the [EnhancementProject](https://ignatandrei.github.io/RSCG_Examples/v2/docs/rscg-examples#enhancementproject) category","Testing"],"readme":"# GRPC-Mock-Server\nSuper fast, platform independent, standalone component for mocking GRPC services using [WireMock.NET](https://github.com/WireMock-Net/WireMock.Net) stubbing engine\n\n## Supported GRPC communication patterns\n\n|Pattern|Implementation status|\n|---|----|\n|request-reply|✅|\n|server-streaming|✅|\n|client-streaming|✅|\n|duplex-streaming|✅|\n\n## How does it work\n\nGRPC-Mock-Server works in the following way:\n- compile provided `*.proto` files\n- generate proxy for every service and method defined in the `*.proto` files\n- use the generated proxy to translate GRPC calls to REST and forward it to `WireMock` backend\n\n```mermaid\nsequenceDiagram    \n    participant Tests\n    participant TestedApp as Tested App\n    box  GRPC-Mock-Server\n    participant Frontend as Fronted [GRPC to HTTP proxy]\n    participant Backend as Backend  [WireMock]\n    end\n    autonumber\n    Tests-\u003e\u003e Backend : Prepare mapping\n    Tests-\u003e\u003e TestedApp: call\n    activate TestedApp\n    TestedApp-\u003e\u003eFrontend: Call GRPC service    \n    activate Frontend\n    Frontend -\u003e\u003e Frontend: Translate GRPC to HTTP\n    Frontend -\u003e\u003e  Backend: Forward HTTP request to WireMock\n    activate Backend\n    Backend --\u003e\u003e Frontend: Respond with matched HTP request\n    deactivate Backend\n     Frontend -\u003e\u003e Frontend: Translate HTTP to GRPC\n    Frontend --\u003e\u003e TestedApp : Return GRPC response\n    deactivate Frontend\n    deactivate TestedApp\n```\n\n\n## How to run GRPC-Mock-Server\n\n### Option 1: Running docker container manually\n\n```\ndocker run -it -p 5033:5033 -p 9095:9095 -v $(pwd)/protos:/protos cezarypiatek/grpc-mock-server\n```\n\nPorts:\n- 5033 for GRPC\n- 9095 for Stubbing (WireMock API)\n\n### Option 2: Using TestContainerGrpcMockServerConnector\n\n`TestContainerGrpcMockServerConnector` uses [Testcontainers for .NET](https://dotnet.testcontainers.org/) to spin docker container directly from the C# code. This options requires docker service running locally.\n\n```cs\nawait using var connector = new TestContainerGrpcMockServerConnector(protoDirectory: \"protos\", grpcPort:5033);\n\nawait connector.Install();\n```\n\n### Option 3: Using TestChartGrpcMockServerConnector\n\n`TestChartGrpcMockServerConnector` uses [SmoothSailing](https://github.com/cezarypiatek/SmoothSailing) to deploy GRPC-Mock-Server into Kubernetes cluster directly from the C# code. This option requires `Helm` and `kubectl` to be installed on the host machine.\n\n```mermaid\nstateDiagram-v2\n\n    state \"K8s Installation\" as g1\n    state \"Pod startup\" as g2\n    state \"Runtime\" as g3\n    state \"Converts proto files to ConfigMap\" as s1\n    state \"Installs Helm Chart with GRPC-Mock-Server\" as s2\n    state \"Mounts ConfigMap with protos as storage to pod\" as s22\n    state \"Compiles proto files\" as s3\n    state \"Generates GRPC-To-HTTP proxy\" as s4\n    state \"Compiles generated code\" as s5\n    state \"Starts host app with GRPC-To-HTTP proxy and WireMock\" as s6\n    state \"Handles GRPC calls\" as s7\n    state \"Handles WireMock calls\" as s8\n     direction LR\n    g1 --\u003e g2\n    g2 --\u003e g3\n    state g1\n    {\n        direction TB\n        s1 --\u003e s2\n        s2 --\u003e s22\n    }\n    state g2 {\n        direction TB       \n        s3 --\u003e s4        \n        s4 --\u003e s5\n        s5 --\u003e s6\n    }\n    state g3{\n        direction TB\n        s7\n        s8 \n    }\n    \n```\n\n```cs\nvar settings = new TestChartGrpcMockServerConnectorSettings\n{\n    ProtoDirectory = \"protos\",\n    GrpcPort = 8889,\n    ExposeStubbingPortOnLocalhost = true\n};\nawait using var connector = new TestChartGrpcMockServerConnector(settings);\n\nvar connectionInfo = await connector.Install();\n```\n\n[![NuGet](https://img.shields.io/nuget/vpre/GrpcTestKit.svg)](https://www.nuget.org/packages/GrpcTestKit/)\n\nAll C# components required for `Option 2` and `Option 3` are provided by [GrpcTestKit nuget package](https://www.nuget.org/packages/GrpcTestKit/) .\n\n```\ndotnet add package GrpcTestKit\n```\n\n### Option 4: Using source generator + proto files\n\n1. Add the following nuget package references\n\n```xml\n\u003cItemGroup\u003e\n    \u003cPackageReference Include=\"Grpc.AspNetCore\" Version=\"2.53.0\" /\u003e\n    \u003cPackageReference Include=\"WireMock.Net\" Version=\"1.5.25\" /\u003e\n    \u003cPackageReference Include=\"GrpcTestKit\" Version=\"1.18.0\" /\u003e\n\u003c/ItemGroup\u003e\n```\n\n2. Include your proto files\n```xml\n\u003cItemGroup\u003e\n    \u003cProtobuf Include=\"protos\\**\\*.proto\" ProtoRoot=\"protos\" GrpcServices=\"Server\" /\u003e\n\u003c/ItemGroup\u003e\n```\n\n3. Define partial class for your mock server\n\n```cs\n[GrpcMockServerForAutoDiscoveredSourceServices]\npublic partial class MyInMemoryGrpcMockServer\n{\n}\n```\n\n3. Use geneated mock server type\n\n```cs\nawait using var mockServer = new MyInMemoryGrpcMockServer(grpcPort: 5033, wireMockPort: 9096);\nvar connectionInfo = await mockServer.Install();\n```\n\n### Option 5: Using source generator + GRPC server stub\n\n1. Add the following nuget package references\n\n```xml\n\u003cItemGroup\u003e\n    \u003cPackageReference Include=\"Grpc.AspNetCore\" Version=\"2.53.0\" /\u003e\n    \u003cPackageReference Include=\"WireMock.Net\" Version=\"1.5.25\" /\u003e\n    \u003cPackageReference Include=\"GrpcTestKit\" Version=\"1.18.0\" /\u003e\n\u003c/ItemGroup\u003e\n```\n\n2. Define partial class for your mock server\n\n```cs\n[GrpcMockServerFor(typeof(Sample.SampleBase))]\npublic partial class MyInMemoryGrpcMockServer\n{\n}\n```\n\n3. Use geneated mock server type\n\n```cs\nawait using var mockServer = new MyInMemoryGrpcMockServer(grpcPort: 5033, wireMockPort: 9096);\nvar connectionInfo = await mockServer.Install();\n```\n\n## How to prepare mocks\n\n```cs\nawait using var connector = new TestContainerGrpcMockServerConnector( protoDirectory: \"protos\", grpcPort:5033);\n\nawait connector.Install();\n\nvar grpcMockClient = connector.CreateClient();\n\nawait grpcMockClient.MockRequestReply\n(\n    serviceName: \"my.package.Sample\",\n    methodName: \"TestRequestReply\",\n    request: new { name = \"Hello 1\" },\n    response: new { message = \"Hi there 1\" }\n);\n\nawait grpcMockClient.MockRequestReply\n(\n    serviceName: \"my.package.Sample\",\n    methodName: \"TestRequestReply\",\n    request: new { name = \"Hello 2\" },\n    response: new { message = \"Hi there 2\" }\n);\n\nawait grpcMockClient.MockServerStreaming\n(\n    serviceName: \"my.package.Sample\",\n    methodName: \"TestServerStreaming\",\n    request: new { name = \"Hello streaming\" },\n    response: new[]\n    {\n        new {message = \"Hi there 1\"},\n        new {message = \"Hi there 2\"},\n        new {message = \"Hi there 3\"}\n    }\n);\n\nawait grpcMockClient.MockClientStreaming\n(\n    serviceName: \"my.package.Sample\",\n    methodName: \"TestServerStreaming\",\n    requests: new []\n    {\n        new { name = \"Hello streaming 1\" },\n        new { name = \"Hello streaming 2\" }\n    },\n    response: new { message = \"Hi there streaming client\" }\n);\n\nawait grpcMockClient.MockDuplexStreaming\n(\n    serviceName: \"my.package.Sample\",\n    methodName: \"TestClientServerStreaming\", \n    scenario: new MessageExchange[]\n    {\n        new ()\n        {\n            Requests = new[]\n            {\n                new {name = \"Ping 1a\"},\n                new {name = \"Ping 1b\"}\n            },\n            Responses = new[]\n            {\n                new {message = \"Pong 1\"}\n            }\n        },\n        new ()\n        {\n            Requests = new[]\n            {\n                new {name = \"Ping 2\"},\n            },\n            Responses = new[]\n            {\n                new {message = \"Pong 2a\"},\n                new {message = \"Pong 2b\"}\n            }\n        },\n});\n```\n\nYou can also generate stub helpers that will simplify your code responsible for preparing mocks/stubs.\n\n\n```cs\n[GrpcMockHelperFor(typeof(Sample.SampleBase))]\npublic partial class SampleMockHelper\n{\n\n}\n```\n\nNow you can prepare your mocks as follows:\n\n```cs\nawait using var connector = new InMemoryGrpcMockServerConnector(grpcPort:5033, wireMockPort: 9594);\n                \n_ = await connector.Install();\n\nvar grpcMockClient = connector.CreateClient();\n\nvar mockHelper = new SampleMockHelper(grpcMockClient);\n\n_ = await mockHelper.MockTestRequestReply\n(\n    request: new HelloRequest {Name = \"Hello 1\"},\n    response: new HelloReply {Message = \"Hi there 1\"}\n);\n\n_ = await mockHelper.MockTestServerStreaming\n(\n    request: new HelloRequest {Name = \"Hello streaming\"},\n    response: new[]\n    {\n        new HelloReply {Message = \"Hi there 1\"},\n        new HelloReply {Message = \"Hi there 2\"},\n        new HelloReply {Message = \"Hi there 2\"},\n    }\n);\n\n_ = await mockHelper.MockTestClientStreaming\n(\n    request: new []\n    {\n        new HelloRequest {Name = \"Hello streaming 1\"},\n        new HelloRequest {Name = \"Hello streaming 2\"},\n    },\n    response: new HelloReply\n    {\n        Message = \"Hi there streaming client\"\n    }\n);\n\n_ = await mockHelper.MockTestClientServerStreaming(new MessageExchange\u003cHelloRequest, HelloReply\u003e[]\n{\n    new()\n    {\n        Requests = new HelloRequest[]\n        {\n            new() {Name = \"Ping 1a\"},\n            new() {Name = \"Ping 1b\"}\n        },\n        Responses = new HelloReply[]\n        {\n            new() {Message = \"Pong 1\"}\n        }\n    },\n    new()\n    {\n        Requests = new HelloRequest[]\n        {\n            new() {Name = \"Ping 2\"},\n        },\n        Responses = new HelloReply[]\n        {\n            new() {Message = \"Pong 2a\"},\n            new() {Message = \"Pong 2b\"}\n        }\n    },\n});\n```\n\n## TODO\n- [ ] Implement error response codes\n- [x] Stub generator\n- [x] Publish source generator as nuget package to allow for hosting GRPC-Mock-Server in-process\n- [x] Implement library that wraps WireMock API for stubbing\n- [x] Implement test container\n\n## Alternatives\n- https://github.com/Adven27/grpc-wiremock\n- https://github.com/tokopedia/gripmock\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcezarypiatek%2FGRPC-Mock-Server","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcezarypiatek%2FGRPC-Mock-Server","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcezarypiatek%2FGRPC-Mock-Server/lists"}