{"id":21453580,"url":"https://github.com/queil/gmox","last_synced_at":"2025-07-14T23:31:49.039Z","repository":{"id":37838250,"uuid":"437857425","full_name":"queil/gmox","owner":"queil","description":".NET-friendly gRPC mock server","archived":false,"fork":false,"pushed_at":"2023-03-02T17:56:03.000Z","size":251,"stargazers_count":7,"open_issues_count":1,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2023-03-25T13:00:05.628Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/queil.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}},"created_at":"2021-12-13T12:05:26.000Z","updated_at":"2023-03-08T16:50:21.000Z","dependencies_parsed_at":"2022-08-09T18:41:46.653Z","dependency_job_id":null,"html_url":"https://github.com/queil/gmox","commit_stats":null,"previous_names":[],"tags_count":null,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/queil%2Fgmox","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/queil%2Fgmox/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/queil%2Fgmox/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/queil%2Fgmox/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/queil","download_url":"https://codeload.github.com/queil/gmox/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":226002930,"owners_count":17558153,"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":[],"created_at":"2024-11-23T04:40:11.585Z","updated_at":"2024-11-23T04:40:12.043Z","avatar_url":"https://github.com/queil.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Gmox ![Azure DevOps coverage](https://img.shields.io/azure-devops/coverage/queil/gmox/4) [![Build Status](https://dev.azure.com/queil/gmox/_apis/build/status/queil.gmox?branchName=main)](https://dev.azure.com/queil/gmox/_build/latest?definitionId=4\u0026branchName=main) [![NuGet Badge](https://buildstats.info/nuget/Queil.Gmox.Dotnet.Cli?includePreReleases=true)](https://www.nuget.org/packages/Queil.Gmox.Dotnet.Cli)\n\n.NET-friendly gRPC mock server inspired by [gripmock](https://github.com/tokopedia/gripmock) powered by [Saturn](https://saturnframework.org/) and F#. It comes both as a dotnet tool and a dotnet template depending on the [use case](#usage).\n\nGmox exposes two endpoints:\n\n* gRPC (port `4770`) serving endpoint\n* HTTP (port `4771`) control endpoint (for dynamic stubbing)\n  * `GET` `/` - lists configured stubs\n  * `POST` `/add` - adds stub configuration\n  * `POST` `/test` - test if the provided data matches any stub\n  * `POST` `/clear` - deletes all the stub configurations\n  * `POST` `/quit` - gracefully terminates the server\n\n## Quick start\n\nInstall the tool:\n```bash\ndotnet tool install --global Queil.Gmox.DotNet.Cli\n```\n\nRun the server:\n\n```bash\n# assuming cd = root of this repo\n# adding two services and the stubs dir contains stubs for both of them\ngmox serve --proto tests/resources/protos/org/books/list/svc_list.proto tests/resources/protos/org/books/add/svc_add.proto --root tests/resources/protos --stub-dir tests/resources/stubs\n```\n\nYou can also use Gmox as a [dotnet template](#dotnet-template).\n\n## FAQ\n\n* Does is support running/stubbing multiple services (and from multiple protos)? ✔️\n\n  Yes, in the dotnet cli mode you can specify multiple proto files after the `--proto` param as long as they're in a common root or self-contained. \n\n* How to override ports?\n\n  **Dotnet tool mode**\n\n  Via cmdline parameters: `--serve-port` and `--control-port`\n\n  **Dotnet template mode**\n\n  * via env vars: `GMOX__PORTS__SERVE` and `GMOX__PORTS__CONTROL`\n  * via cmdline parameters: `--gmox:ports:serve=` and `--gmox:ports:control=`\n  * via any other method supported by `IConfiguration` (Microsoft.Extensions.Configuration)\n  \n## Stubbing configuration\n\nStub configuration consists of a fully-qualified method name (like `grpc.health.v1.Health/Check`),\na rule that matches incoming requests data, and a corresponding response data attached to it.\n\nThere are two ways of configuring stubs (which work both in the dotnet tool and the dotnet template):\n\n### Static JSON files\n\nStatic files should contain valid JSON arrays of stub configurations, have the `.json` extension, and they should be located in the directory:\n\n* in dotnet cli mode - given by the `--stub-dir` command line parameter \n* in dotnet template mode - defined in `App.fs` as `StubPreloadDir`\n\n### Dynamic REST API configuration\n\nSingle stub configurations (not arrays) can be `POST`ed to the `/add` endpoint at port `4771` like:\n\n```bash\ncurl -X POST http://localhost:4771/add -d '{ \"method\": \"grpc.health.v1.Health/Check\", \"match\": { \"exact\": {} }, \"return\": { \"data\": { \"status\": \"NOT_SERVING\" } } }'\n```\n\n### Stub configuration JSON explained\n\nGiven the server receives a call to the `grpc.health.v1.Health/Check` method and the message is `{}` (empty) then it returns `{\"status\": \"SERVING\"}`.\n\n```json\n{\n  \"method\": \"grpc.health.v1.Health/Check\",\n  \"match\": {\n    \"exact\": {}\n  }, \n  \"return\": {\n    \"data\": {\n      \"status\": \"SERVING\"\n    }\n  }\n}\n```\n\nStubs can be configured using the following rules:\n\n* `exact` - matches if the request is exactly the same as the stub input\n* `partial` - matches if the stub input data is a sub-tree of the request data\n* `regex` - like `partial` but values in requests can be matched with a regular expression\n\nWhenever a gRPC call is received the request data is evaluated against the available stub configurations.\nMultiple stubs can be configured for a gRPC method and they're evaluated from the most (`exact`) to the least (`regex`) specific.\nThe first match wins.\n\n## Usage\n\n:information_source: All of the below modes support both static and dynamic stubbing.\n\n### Dotnet CLI tool\n\nGmox as a dotnet CLI tool is useful in development scenarios when you want to quickly create a mock\nserver from protos.\n\nInstallation: `dotnet tool install --global Queil.Gmox.DotNet.Cli`\n\nUsage: \n\nRun `gmox`:\n\n```bash\n# assuming cd = root of this repo\ngmox serve --proto tests/resources/protos/org/books/list/svc_list.proto tests/resources/protos/org/books/add/svc_add.proto --root tests/resources/protos --stub-dir tests/resources/stubs\n```\n\nYou can play with the mock using `grpcui` if needed: `grpcui -plaintext  localhost:4770`\n\n### Dotnet Template\n\nGmox as a dotnet template is useful when you want to create a mock server for a particular service, equip it with a curated set of default rules, and/or it runs in an environment where you have no access to protos.\n\nThe template makes following assumptions out-of-the-box:\n\n* references the NuGet package provided as a parameter\n* auto-registers all the services from the assembly marked with a type (fully-qualified) passed as a parameter\n\nInstallation: `dotnet new --install Queil.Gmox.Template`\n\nUsage: `dotnet new gmox -h`\n\n### Docker image\n\nBoth the CLI tool and a server generated from the template may be packaged as Docker image and used in scenarios where having .NET SDK is not desirable.\n\n## TODO\n\n* [x] Unit tests!\n* [ ] Docs!\n  * [ ] Add examples for API endpoints\n* [x] Support dynamic stubbing:\n  * [x] `exact`\n  * [x] `partial`\n  * [x] `regexp`\n* [ ] Handle errors:\n  * [ ] `/add` - if input JSON is not a valid request for the specified service method\n  * [x] `/add` - if user tries configure a stub for a non-existent ~~service~~ method\n* [x] Support the following source of service schemas:\n  1. [x] NuGet package (compile-time - as a dotnet project template, useful when we have no access to protos) \n  2. [x] Protos (runtime - as a dotnet tool, useful on local dev when we do have protos and iterate quickly)\n\n* [ ] Support recording received calls and expose via the control API\n* [ ] Support requesting JSON-formatted request/responses so they can make creating stubs easier\n* [x] Support preloading stubs form JSON\n* [x] Support specifying port numbers\n* [ ] Support returning errors\n* [ ] CI: make push stage only run after the whole test matrix passes\n\n## Development\n\n### Testing `Queil.Gmox.Template`\n\n```bash\nDIR=./src/Queil.Gmox.Template/template \u0026\u0026 dotnet new --install $DIR\n# then in another dir\ndotnet new gmox -nu Your.NuGet.Package -amt Your.NuGet.Package.Assembly.Type\n```\n\nOnce the template is installed it can be refreshed by:\n\n```bash\ndotnet new --debug:rebuildcache\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fqueil%2Fgmox","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fqueil%2Fgmox","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fqueil%2Fgmox/lists"}