Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/cezarypiatek/grpc-mock-server
Super fast, platform independent, standalone component for mocking GRPC services using WireMock.NET stubbing engine
https://github.com/cezarypiatek/grpc-mock-server
csharp-sourcegenerator grpc http mock-server mocking stubbing
Last synced: about 10 hours ago
JSON representation
Super fast, platform independent, standalone component for mocking GRPC services using WireMock.NET stubbing engine
- Host: GitHub
- URL: https://github.com/cezarypiatek/grpc-mock-server
- Owner: cezarypiatek
- License: mit
- Created: 2023-05-16T21:04:02.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2023-10-09T21:03:40.000Z (about 1 year ago)
- Last Synced: 2024-11-08T20:45:40.236Z (8 days ago)
- Topics: csharp-sourcegenerator, grpc, http, mock-server, mocking, stubbing
- Language: C#
- Homepage:
- Size: 90.8 KB
- Stars: 32
- Watchers: 2
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# GRPC-Mock-Server
Super fast, platform independent, standalone component for mocking GRPC services using [WireMock.NET](https://github.com/WireMock-Net/WireMock.Net) stubbing engine## Supported GRPC communication patterns
|Pattern|Implementation status|
|---|----|
|request-reply|✅|
|server-streaming|✅|
|client-streaming|✅|
|duplex-streaming|✅|## How does it work
GRPC-Mock-Server works in the following way:
- compile provided `*.proto` files
- generate proxy for every service and method defined in the `*.proto` files
- use the generated proxy to translate GRPC calls to REST and forward it to `WireMock` backend```mermaid
sequenceDiagram
participant Tests
participant TestedApp as Tested App
box GRPC-Mock-Server
participant Frontend as Fronted [GRPC to HTTP proxy]
participant Backend as Backend [WireMock]
end
autonumber
Tests->> Backend : Prepare mapping
Tests->> TestedApp: call
activate TestedApp
TestedApp->>Frontend: Call GRPC service
activate Frontend
Frontend ->> Frontend: Translate GRPC to HTTP
Frontend ->> Backend: Forward HTTP request to WireMock
activate Backend
Backend -->> Frontend: Respond with matched HTP request
deactivate Backend
Frontend ->> Frontend: Translate HTTP to GRPC
Frontend -->> TestedApp : Return GRPC response
deactivate Frontend
deactivate TestedApp
```## How to run GRPC-Mock-Server
### Option 1: Running docker container manually
```
docker run -it -p 5033:5033 -p 9095:9095 -v $(pwd)/protos:/protos cezarypiatek/grpc-mock-server
```Ports:
- 5033 for GRPC
- 9095 for Stubbing (WireMock API)### Option 2: Using TestContainerGrpcMockServerConnector
`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.
```cs
await using var connector = new TestContainerGrpcMockServerConnector(protoDirectory: "protos", grpcPort:5033);await connector.Install();
```### Option 3: Using TestChartGrpcMockServerConnector
`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.
```mermaid
stateDiagram-v2state "K8s Installation" as g1
state "Pod startup" as g2
state "Runtime" as g3
state "Converts proto files to ConfigMap" as s1
state "Installs Helm Chart with GRPC-Mock-Server" as s2
state "Mounts ConfigMap with protos as storage to pod" as s22
state "Compiles proto files" as s3
state "Generates GRPC-To-HTTP proxy" as s4
state "Compiles generated code" as s5
state "Starts host app with GRPC-To-HTTP proxy and WireMock" as s6
state "Handles GRPC calls" as s7
state "Handles WireMock calls" as s8
direction LR
g1 --> g2
g2 --> g3
state g1
{
direction TB
s1 --> s2
s2 --> s22
}
state g2 {
direction TB
s3 --> s4
s4 --> s5
s5 --> s6
}
state g3{
direction TB
s7
s8
}
``````cs
var settings = new TestChartGrpcMockServerConnectorSettings
{
ProtoDirectory = "protos",
GrpcPort = 8889,
ExposeStubbingPortOnLocalhost = true
};
await using var connector = new TestChartGrpcMockServerConnector(settings);var connectionInfo = await connector.Install();
```[![NuGet](https://img.shields.io/nuget/vpre/GrpcTestKit.svg)](https://www.nuget.org/packages/GrpcTestKit/)
All C# components required for `Option 2` and `Option 3` are provided by [GrpcTestKit nuget package](https://www.nuget.org/packages/GrpcTestKit/) .
```
dotnet add package GrpcTestKit
```### Option 4: Using source generator + proto files
1. Add the following nuget package references
```xml
```
2. Include your proto files
```xml
```
3. Define partial class for your mock server
```cs
[GrpcMockServerForAutoDiscoveredSourceServices]
public partial class MyInMemoryGrpcMockServer
{
}
```3. Use geneated mock server type
```cs
await using var mockServer = new MyInMemoryGrpcMockServer(grpcPort: 5033, wireMockPort: 9096);
var connectionInfo = await mockServer.Install();
```### Option 5: Using source generator + GRPC server stub
1. Add the following nuget package references
```xml
```
2. Define partial class for your mock server
```cs
[GrpcMockServerFor(typeof(Sample.SampleBase))]
public partial class MyInMemoryGrpcMockServer
{
}
```3. Use geneated mock server type
```cs
await using var mockServer = new MyInMemoryGrpcMockServer(grpcPort: 5033, wireMockPort: 9096);
var connectionInfo = await mockServer.Install();
```## How to prepare mocks
```cs
await using var connector = new TestContainerGrpcMockServerConnector( protoDirectory: "protos", grpcPort:5033);await connector.Install();
var grpcMockClient = connector.CreateClient();
await grpcMockClient.MockRequestReply
(
serviceName: "my.package.Sample",
methodName: "TestRequestReply",
request: new { name = "Hello 1" },
response: new { message = "Hi there 1" }
);await grpcMockClient.MockRequestReply
(
serviceName: "my.package.Sample",
methodName: "TestRequestReply",
request: new { name = "Hello 2" },
response: new { message = "Hi there 2" }
);await grpcMockClient.MockServerStreaming
(
serviceName: "my.package.Sample",
methodName: "TestServerStreaming",
request: new { name = "Hello streaming" },
response: new[]
{
new {message = "Hi there 1"},
new {message = "Hi there 2"},
new {message = "Hi there 3"}
}
);await grpcMockClient.MockClientStreaming
(
serviceName: "my.package.Sample",
methodName: "TestServerStreaming",
requests: new []
{
new { name = "Hello streaming 1" },
new { name = "Hello streaming 2" }
},
response: new { message = "Hi there streaming client" }
);await grpcMockClient.MockDuplexStreaming
(
serviceName: "my.package.Sample",
methodName: "TestClientServerStreaming",
scenario: new MessageExchange[]
{
new ()
{
Requests = new[]
{
new {name = "Ping 1a"},
new {name = "Ping 1b"}
},
Responses = new[]
{
new {message = "Pong 1"}
}
},
new ()
{
Requests = new[]
{
new {name = "Ping 2"},
},
Responses = new[]
{
new {message = "Pong 2a"},
new {message = "Pong 2b"}
}
},
});
```You can also generate stub helpers that will simplify your code responsible for preparing mocks/stubs.
```cs
[GrpcMockHelperFor(typeof(Sample.SampleBase))]
public partial class SampleMockHelper
{}
```Now you can prepare your mocks as follows:
```cs
await using var connector = new InMemoryGrpcMockServerConnector(grpcPort:5033, wireMockPort: 9594);
_ = await connector.Install();var grpcMockClient = connector.CreateClient();
var mockHelper = new SampleMockHelper(grpcMockClient);
_ = await mockHelper.MockTestRequestReply
(
request: new HelloRequest {Name = "Hello 1"},
response: new HelloReply {Message = "Hi there 1"}
);_ = await mockHelper.MockTestServerStreaming
(
request: new HelloRequest {Name = "Hello streaming"},
response: new[]
{
new HelloReply {Message = "Hi there 1"},
new HelloReply {Message = "Hi there 2"},
new HelloReply {Message = "Hi there 2"},
}
);_ = await mockHelper.MockTestClientStreaming
(
request: new []
{
new HelloRequest {Name = "Hello streaming 1"},
new HelloRequest {Name = "Hello streaming 2"},
},
response: new HelloReply
{
Message = "Hi there streaming client"
}
);_ = await mockHelper.MockTestClientServerStreaming(new MessageExchange[]
{
new()
{
Requests = new HelloRequest[]
{
new() {Name = "Ping 1a"},
new() {Name = "Ping 1b"}
},
Responses = new HelloReply[]
{
new() {Message = "Pong 1"}
}
},
new()
{
Requests = new HelloRequest[]
{
new() {Name = "Ping 2"},
},
Responses = new HelloReply[]
{
new() {Message = "Pong 2a"},
new() {Message = "Pong 2b"}
}
},
});
```## TODO
- [ ] Implement error response codes
- [x] Stub generator
- [x] Publish source generator as nuget package to allow for hosting GRPC-Mock-Server in-process
- [x] Implement library that wraps WireMock API for stubbing
- [x] Implement test container## Alternatives
- https://github.com/Adven27/grpc-wiremock
- https://github.com/tokopedia/gripmock