{"id":13741039,"url":"https://github.com/Fadelis/grpcmock","last_synced_at":"2025-05-08T21:32:05.843Z","repository":{"id":38375111,"uuid":"210049997","full_name":"Fadelis/grpcmock","owner":"Fadelis","description":"A gRPC Java testing tool to easily mock endpoints of gRPC services for IT or Unit testing","archived":false,"fork":false,"pushed_at":"2024-11-07T07:36:05.000Z","size":340,"stargazers_count":146,"open_issues_count":2,"forks_count":13,"subscribers_count":6,"default_branch":"master","last_synced_at":"2024-11-07T08:29:06.528Z","etag":null,"topics":["grpc","grpc-integration-testing","grpc-it","grpc-java","grpc-java-testing","grpc-mock","grpc-mocking","grpc-services","grpc-testing","grpc-unit","grpc-wiremock","junit5","mapping-stubs","mocking","spring-boot"],"latest_commit_sha":null,"homepage":"http://grpcmock.org","language":"Java","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/Fadelis.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,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-09-21T20:34:16.000Z","updated_at":"2024-11-07T07:36:09.000Z","dependencies_parsed_at":"2023-11-10T14:41:37.798Z","dependency_job_id":"9b0090df-88a1-4a43-b69e-011dec61606d","html_url":"https://github.com/Fadelis/grpcmock","commit_stats":null,"previous_names":[],"tags_count":42,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Fadelis%2Fgrpcmock","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Fadelis%2Fgrpcmock/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Fadelis%2Fgrpcmock/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Fadelis%2Fgrpcmock/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Fadelis","download_url":"https://codeload.github.com/Fadelis/grpcmock/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224742564,"owners_count":17362232,"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":["grpc","grpc-integration-testing","grpc-it","grpc-java","grpc-java-testing","grpc-mock","grpc-mocking","grpc-services","grpc-testing","grpc-unit","grpc-wiremock","junit5","mapping-stubs","mocking","spring-boot"],"created_at":"2024-08-03T04:00:54.786Z","updated_at":"2024-11-15T11:30:45.192Z","avatar_url":"https://github.com/Fadelis.png","language":"Java","funding_links":[],"categories":["Language-Specific","测试","Java"],"sub_categories":["Java"],"readme":"# gRPC Mock ![Build pipeline](https://github.com/Fadelis/grpcmock/workflows/Build%20pipeline/badge.svg)\n\nA gRPC Java testing tool to easily mock endpoints of gRPC services for IT or Unit testing.\nThe tool follows a similar DSL type of structure to HTTP mocking service [WireMock](https://github.com/tomakehurst/wiremock).\n\n## Features\n\n - gRPC method stubbing configurable through a fluent Java API\n - Headers and request body matchers to determine the correct stub\n - Configurable delay for individual responses\n - Verifiable method invocations for specific method\n - Supported gRPC method types:\n    - Unary methods\n    - Server streaming methods\n    - Client streaming methods\n    - Bidi stream methods\n\n## Quick usage\n\n### Unary methods\n\n```java\nstubFor(unaryMethod(SimpleServiceGrpc.getUnaryRpcMethod())\n    .willReturn(response1));\n\nstubFor(unaryMethod(SimpleServiceGrpc.getUnaryRpcMethod())\n    .withHeader(\"header-1\", \"value-1\")\n    .withHeader(\"header-2\", value -\u003e value.startsWith(\"value\"))\n    .withRequest(expectedRequest)\n    .willReturn(response(response1)\n        .withFixedDelay(200)) // first invocation will return this response after 200 ms\n    .nextWillReturn(response(response2))); // subsequent invocations will return this response\n```\n\nSee more [examples](grpcmock-core/src/test/java/org/grpcmock/GrpcMockUnaryMethodTest.java)\n\n### Server streaming methods\n\n```java\nstubFor(serverStreamingMethod(SimpleServiceGrpc.getServerStreamingRpcMethod())\n    .willReturn(responses1, responses2, responses3)); // return one by one with no delay\n\nstubFor(serverStreamingMethod(SimpleServiceGrpc.getServerStreamingRpcMethod())\n    .withHeader(\"header-1\", \"value-1\")\n    .withRequest(req -\u003e req.getRequestMessage().endsWith(\"1\"))\n    .willReturn(stream(response(responses1).withFixedDelay(200))\n        .and(response(responses2).withFixedDelay(100))\n        .and(response(responses3).withFixedDelay(200)))\n    .nextWillReturn(statusException(Status.NOT_FOUND))); // subsequent invocations will return status exception\n```\n\nSee more [examples](grpcmock-core/src/test/java/org/grpcmock/GrpcMockServerStreamingMethodTest.java)\n\n### Client streaming methods\n\nStubs for client streaming method calls are selected on receiving first stream request message.\n\n```java\nstubFor(clientStreamingMethod(SimpleServiceGrpc.getClientStreamingRpcMethod())\n    .willReturn(responses1)); // return a response on completed client streaming requests\n\nstubFor(clientStreamingMethod(SimpleServiceGrpc.getClientStreamingRpcMethod())\n    .withHeader(\"header-1\", \"value-1\")\n    .withFirstRequest(req -\u003e req.getRequestMessage().endsWith(\"1\"))\n    .willReturn(response(responses1).withFixedDelay(200))\n    .nextWillReturn(statusException(Status.NOT_FOUND))); // subsequent invocations will return status exception\n```\n\nSee more [examples](grpcmock-core/src/test/java/org/grpcmock/GrpcMockClientStreamingMethodTest.java)\n\n### Bidi streaming methods\n\nStubs for bidi streaming method calls are selected on receiving first stream request message.\n\n```java\nstubFor(bidiStreamingMethod(SimpleServiceGrpc.getBidiStreamingRpcMethod())\n    .withHeader(\"header-1\", \"value-1\")\n    .withFirstRequest(req -\u003e req.getRequestMessage().endsWith(\"1\"))\n    .willProxyTo(responseObserver -\u003e new StreamObserver\u003cSimpleRequest\u003e() {\n        @Override\n        public void onNext(SimpleRequest request) {\n          SimpleResponse response = SimpleResponse.newBuilder()\n            .setResponseMessage(request.getRequestMessage())\n            .build();\n          responseObserver.onNext(response);\n        }\n        \n        @Override\n        public void onError(Throwable error) {\n          // handle error\n        }\n        \n        @Override\n        public void onCompleted() {\n          responseObserver.onCompleted();\n        }\n    }));\n```\n\nSee more [examples](grpcmock-core/src/test/java/org/grpcmock/GrpcMockBidiStreamingMethodTest.java)\n\n### Verifying invocation count\n\n```java\nverifyThat(\n    calledMethod(getUnaryRpcMethod())\n        .withStatusOk()\n        .withHeader(\"header-1\", \"value-1\")\n        .withRequest(request),\n    times(3));\n\nverifyThat(getUnaryRpcMethod(), never());\n\nverifyThat(\n    calledMethod(getClientStreamingRpcMethod())\n        .withNumberOfRequests(2)\n        .withFirstRequest(request)\n        .withRequestAtIndex(1, request2));\n```\n\nSee more [examples](grpcmock-core/src/test/java/org/grpcmock/GrpcMockVerifyTest.java)\n\n## Integrations\n\nSee example [projects](grpcmock-examples)\n\n### Spring-Boot\n\ngRPC Mock integrates with Spring-Boot via `grpcmock-spring-boot` module.\n\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003eorg.grpcmock\u003c/groupId\u003e\n  \u003cartifactId\u003egrpcmock-spring-boot\u003c/artifactId\u003e\n  \u003cversion\u003e0.15.0\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nYou have to declare the `@AutoConfigureGrpcMock` for the test class to enable gRPC Mock:\n\n```java\n@SpringJUnitConfig\n@SpringBootTest(classes = Application.class, webEnvironment = WebEnvironment.NONE)\n@AutoConfigureGrpcMock\nclass TestClass {\n\n  @Value(\"${grpcmock.server.port}\")\n  private int grpcMockPort;\n\n  private ManagedChannel channel;\n\n  @BeforeEach\n  void setupChannel() {\n    channel = ManagedChannelBuilder.forAddress(\"localhost\", grpcMockPort)\n        .usePlaintext()\n        .build();\n  }\n\n  @AfterEach\n  void shutdownChannel() {\n    Optional.ofNullable(channel).ifPresent(ManagedChannel::shutdownNow);\n  }\n}\n```\n\nIf the gRPC Mock port is set to 0, then a random port will be selected for the server.\nIt is the recommended approach to improve test run times.\nOnce a random port is selected it can be accessed via `${grpcmock.server.port}` property and used in gRPC `Channel` creation.\n\nIt's also possible to use InProcess server with Spring-Boot\n\n```java\n@SpringJUnitConfig\n@SpringBootTest(classes = Application.class, webEnvironment = WebEnvironment.NONE)\n@AutoConfigureGrpcMock(useInProcessServer = true)\nclass TestClass {\n\n   @Value(\"${grpcmock.server.name}\")\n   private String inProcessName;\n\n   private ManagedChannel channel;\n\n   @BeforeEach\n   void setupChannel() {\n      channel = InProcessChannelBuilder.forName(inProcessName).build();\n   }\n\n   @AfterEach\n   void shutdownChannel() {\n      Optional.ofNullable(channel).ifPresent(ManagedChannel::shutdownNow);\n   }\n}\n```\n\nIf you don't set `name()` in `@AutoConfigureGrpcMock` then it will be generated randomly.\nBeware that it's not possible to create two InProcess servers at once so in case of fixed names\nyou will have to configure a unique name for each spring context. If a random name is used\nit can be accessed via `${grpcmock.server.name}` property and used in gRPC `Channel` creation.\n\nTo remove logging of incoming requests, logging level for GrpcMock should be changed in `application-test.yml`:\n\n```yaml\nlogging.level.org.grpcmock.GrpcMock: WARN\n```\n\n### JUnit5\n\ngRPC Mock integrates with JUnit5 via `grpcmock-junit5` module.\n\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003eorg.grpcmock\u003c/groupId\u003e\n  \u003cartifactId\u003egrpcmock-junit5\u003c/artifactId\u003e\n  \u003cversion\u003e0.15.0\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\nYou can integrate gRPC Mock with default configuration for a JUnit5 test via `@ExtendWith` annotation:\n\n```java\n@ExtendWith(GrpcMockExtension.class)\nclass TestClass {\n\n  private ManagedChannel channel;\n\n  @BeforeEach\n  void setupChannel() {\n    channel = ManagedChannelBuilder.forAddress(\"localhost\", GrpcMock.getGlobalPort())\n        .usePlaintext()\n        .build();\n  }\n\n  @AfterEach\n  void shutdownChannel() {\n    Optional.ofNullable(channel).ifPresent(ManagedChannel::shutdownNow);\n  }\n}\n```\n\nFor quicker unit test execution you can integrate gRPC Mock using an in-process server via `InProcessGrpcMockExtension` extension:\n\n```java\n@ExtendWith(InProcessGrpcMockExtension.class)\nclass TestClass {\n\n  private ManagedChannel channel;\n\n  @BeforeEach\n  void setupChannel() {\n    channel = InProcessChannelBuilder.forName(GrpcMock.getGlobalInProcessName())\n        .usePlaintext()\n        .build();\n  }\n\n  @AfterEach\n  void shutdownChannel() {\n    Optional.ofNullable(channel).ifPresent(ManagedChannel::shutdownNow);\n  }\n}\n```\n\nAlternatively, you can configure gRPC Mock programmatically using `@RegisterExtension` annotation:\n\n```java\nclass TestClass {\n\n  @RegisterExtension\n  static GrpcMockExtension grpcMockExtension = GrpcMockExtension.builder()\n      .withPort(0)\n      .withInterceptor(new MyServerInterceptor())\n      .build();\n  private ManagedChannel channel;\n\n  @BeforeEach\n  void setupChannel() {\n    channel = ManagedChannelBuilder.forAddress(\"localhost\", GrpcMock.getGlobalPort())\n        .usePlaintext()\n        .build();\n  }\n\n  @AfterEach\n  void shutdownChannel() {\n    Optional.ofNullable(channel).ifPresent(ManagedChannel::shutdownNow);\n  }\n}\n```\n\nIn both variants the port for the gRPC Mock server can be retrieved via `GrpcMock.getGlobalPort()`. Mapping stubs will be cleared\nafter each test run and after all tests in the test class are done the server will be shutdown.\n\nTo remove logging of incoming requests, logging level for GrpcMock should be changed depending on the logging backend used. E.g.\nwhen using `slf4j-simple` backend a file `simplelogger.properties` needs to be created in test `resouces` with content:\n\n```yaml\norg.slf4j.simpleLogger.log.org.grpcmock.GrpcMock=warn\n```\n\n### Working in multithreaded test setup\n\nWhen working in multithreaded test setup, where the test class is initiated on one thread and test methods are called on a\ndifferent one, you will encounter `UNIMPLEMENTED` errors when trying to use the static configuration methods. GrpcMock uses a \n`ThreadLocal` instance of `GrpcMock` when using all the static methods, so it will be a different instance on different threads.\n\nTo work with `GrpcMock` in such cases you'll need to have access to the `grpcMock` instance object in your test class.\n\nIn Spring-Boot setup:\n```java\n@SpringJUnitConfig\n@SpringBootTest(classes = Application.class, webEnvironment = WebEnvironment.NONE)\n@AutoConfigureGrpcMock\nclass TestClass {\n  \n  @Autowire\n  private GrpcMock grpcMock;\n}\n```\n\nIn other setups:\n```java\nclass TestClass {\n  \n  private GrpcMock grpcMock = GrpcMock.grpcMock().build().start();\n}\n```\n\nThen when configuring your stubs you can either call the non-static methods directly on the instance in your test methods:\n```java\n@Test\nvoid should_test_something() {\n  grpcMock.register(unaryMethod(SimpleServiceGrpc.getUnaryRpcMethod())\n        .willReturn(response));\n  \n  ... test code\n        \n  grpcMock.verifyThat(calledMethod(SimpleServiceGrpc.getUnaryRpcMethod()).build(), CountMatcher.once());\n}\n```\n\nAlternatively you could call `GrpcMock.configureFor` method with the grpcMock instance in the test class at the beginning \nof each test:\n```java\n@Test\nvoid should_test_something() {\n  configureFor(grpMock);\n  stubFor(unaryMethod(SimpleServiceGrpc.getUnaryRpcMethod())\n        .willReturn(response));\n  \n  ... test code\n        \n  verifyThat(calledMethod(SimpleServiceGrpc.getUnaryRpcMethod()));\n}\n```\nOr depending whether `BeforeEach` method is called on the same thread as the test method that could be done in `BeforeEach` method:\n```java\n@BeforeEach\nvoid setup() {\n  configureFor(grpcMock);\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FFadelis%2Fgrpcmock","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FFadelis%2Fgrpcmock","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FFadelis%2Fgrpcmock/lists"}