Giter VIP home page Giter VIP logo

karate-grpc's Introduction

karate-grpc

Build Status Maven Central

simple gRPC testing with karate and a dynamic client using polyglot.

karate-grpc makes it easy to:

  • build complex protobuf request payloads via json
  • traverse data within the responses
  • chain data from responses into the next request.

Hello World

karate-grpc-hello-world

Testing hello world

Requires maven to be installed

$ # compile and test the whole project
$ mvn clean install

$ # test demo
$ cd karate-grpc-demo
$ mvn test
$ # or run single test
$ mvn test -Dtest=HelloWorldNewRunner

When running tests, the hello world grpc server is started/stopped automatically in AbstractTestBase.java.

Karate also generates beautiful test reports:

karate-grpc-hello-world-report

Real World Examples

A set of real-life examples which includes single rpc, client stream rpc, server stream rpc and bidi stream rpc can be found here: karate-grpc-demo

Getting Started

karate-grpc requires Java 8 and then Maven to be installed, these also are required by karate and polyglot.

karate-grpc only support Maven currently.

Maven

You need to add the following <dependencies>:

<dependency>
    <groupId>com.github.thinkerou</groupId>
    <artifactId>karate-grpc-core</artifactId>
    <version>1.0.7</version>
</dependency>

Gradle

TODO: need to test!!!

Alternatively for Gradle you need to add the following entry:

testImplementation 'com.github.thinkerou:karate-grpc-core:1.0.7'

And simulates karate-grpc-helper and karate-grpc-demo build your redis helper project and test project.

What to need for testing grpc server

Testing one grpc server, we have the follow info:

  • grpc server ip and port.

  • (optional) protobuf file corresponding grpc server, but usually it's protobuf jar package not one single file or more files.

So, we could test it based on the two point.

⚠️ Using karate-grpc we can perfect to solve it!

What to need in pom file

For testing your grpc server, as above, need protobuf jar dependency and protobuf build plugins - protobuf-maven-plugin.

MUST appoint descriptorSetFileName and protoSourceRoot params:

<descriptorSetFileName>karate-grpc.protobin</descriptorSetFileName>
<protoSourceRoot>${project.build.directory}/dependency/demo</protoSourceRoot>

Especially, descriptorSetFileName MUST equal karate-grpc.protobin, please see here about more details.

And other pom settings are the same as karate.

How to write karate feature

We need to use Java interop of Karate in order to call us define grpc client.

And use JSON.parse javascript function parse the response of grpc server return value.

So, use karate-grpc need the following steps:

  1. Calls into karate-grpc GrpcClient via Java Interop.
* def GrpcClient = Java.type('com.github.thinkerou.karate.GrpcClient')
  1. Builds one public Grpc client using your grpc ip and port.
* def client = new GrpcClient('localhost', 50051)

If you want to list protobuf by service name or/and message name, you should use:

* def client = new GrpcClient()

Because you don't need grpc server ip/port when listing protobuf.

  1. Reads JSON data corresponding your protobuf definition.

  2. Calls your Grpc server using call of karate-grpc.

* def response = client.call('helloworld.Greeter/SayHello', payload, karate)

call has two required params, and one optional

  1. protobuf full name(format:<package-name>.<service-name>/<rpc-name>)
  2. JSON data.
  3. karate (optional, nullable) -- if present, will add [request] and [response] to html report. karate variable is of type ScenarioBridge and is automatically created when running karate tests.

request-response-report

If you input protobuf full name error, call will fail and output protobuf message by list, like this:

When input helloworld.Greeter/SayHello1, it will fail and print log:

Oct 11, 2018 6:53:24 PM com.github.thinkerou.karate.service.GrpcCall invoke
警告: Call grpc failed, maybe you should see the follow grpc information.
Oct 11, 2018 6:53:24 PM com.github.thinkerou.karate.service.GrpcCall invoke
信息: [
  {
    "helloworld.Greeter/SayHelloBiStreaming":"",
    "helloworld.Greeter/RecordRoute":"",
    "helloworld.Greeter/RouteChat":"",
    "helloworld.Greeter/SayHelloServerStreaming":"",
    "helloworld.Greeter/ListFeatures":"",
    "helloworld.Greeter/SayHello":"",
    "helloworld.Greeter/AgainSayHello":"",
    "helloworld.Greeter/SayHelloClientStreaming":"",
    "helloworld.Greeter/GetFeature":""
  }
]

  1. Converts response string to JSON.
* def response = JSON.parse(response)

Because call of karate-grpc returns JSON string, we need to convert it and then can use match assertion.

  1. Asserts payload.

  2. (Optional) Saves response for second Grpc.

If have second Grpc use the response of first Grpc, we should save it, like:

* def message = response[0].message

And use it on JSON file:

[
  {
    "message": "#(message)",
    "address": "BeiJing"
  }
]
  1. (Optional) Second Grpc call using response data before.

One whole example likes this:

Feature: grpc helloworld example by grpc dynamic client

  Background:
    * def client = Java.type('demo.DemoGrpcClientSingleton').INSTANCE.getGrpcClient();

  Scenario: do it
    * string payload = read('helloworld.json')
    * def response = client.call('helloworld.Greeter/SayHello', payload)
    * def response = JSON.parse(response)
    * print response
    * match response[0].message == 'Hello thinkerou'
    * def message = response[0].message

    * string payload = read('again-helloworld.json')
    * def response = client.call('helloworld.Greeter/AgainSayHello', payload)
    * def response = JSON.parse(response)
    * match response[0].details == 'Details Hello thinkerou in BeiJing'

How to write JSON file

Because karate-grpc supports stream grpc, we use list JSON.

Input JSON file like:

[
  {
    "name": "thinkerou"
  },
  {
    "name": "thinkerou2"
  }
]

Output JSON string also like:

[
  {
    "message": "Hello thinkerou"
  },
  {
    "message": "Hello thinkerou2"
  }
]

That's all!!!

Redis

Why use Redis?

Using redis is optional, but caching descriptor sets may save compile time, especially when your project has many protobuf jar package dependencies.

Mock Redis

You can even use jedis-mock so you don't even need to install Redis. see MockRedisHelperSingleton.java:

Redis performance

Note: while the redis test implementation is thread-safe, Redis uses single-threaded execution so test performance may be degraded for high concurrency.

To use redis, use class com.github.thinkerou.karate.RedisGrpcClient instead of com.github.thinkerou.karate.GrpClient

example:

public enum DemoGrpcClientSingleton {
    INSTANCE;

    RedisGrpcClient redisGrpcClient;

    public GrpcClient getGrpcClient() {
        return redisGrpcClient;
    }

    DemoGrpcClientSingleton() {
        redisGrpcClient = new RedisGrpcClient("localhost", 50051, MockRedisHelperSingleton.INSTANCE.getRedisHelper());
    }
}

TODO:

  • Save ProtoFullName|InputType|InputMessage|OutputType|OutputMessage|ProtoFileName|RPCAddress not file content.
  • Support java reflection mode.

How to write grpc client

Note:

  • The part content is outdated draft which initially think about the topic which continues to have saved is for reference only.
  • Usually you no need to care it and skip it, because karate-grpc-core have completed the function.

You only need two steps:

  • Read json file and parse protobuf object to the request of grpc server

  • format the response of grpc server to json string and return it as grpc server

Like this:

public class Client {

  // ...

  public static String greet(String input) {
    HelloRequest.Builder requestBuilder = HelloRequest.newBuilder();
    try {
      JsonFormat.parser().merge(input, requestBuilder);
    } catch (ProtocolBufferException e) {
      // ...
    }

    HelloReply response = null;
    try {
      response = blockingStub.sayHello(requestBuilder.build());
    } catch (StatusRuntimeException e) {
      // ...
    }

    String res = "";
    try {
      res = JsonFormat.printer().print(response);
    } catch (ProtocolBufferException e) {
      // ...
    }

    return res;
  }

  // ...
}

Thanks

Thanks Peter Thomas for his work for karate and his generous help, also thanks Dino Wernli for his contributions for polyglot. And the favicon of organization generate at favicon.io.

Reference

Maybe you want to know more information about Karate or other, please read the follow contents:

License

karate-grpc is licensed under MIT License.

karate-grpc's People

Contributors

avyasbms avatar celebrate-future avatar dependabot[bot] avatar ericdriggs avatar mrlonelyjtr avatar pazaan avatar rkuthala avatar thinkerou avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

karate-grpc's Issues

JsonFormat parse fail

proto likes:

message {
  string message = 1;
  string address = 2;
}

input likes:

[
  {
    "message": "hello thinkerou",
    "name": "beijing"
  }
]

when calls JsonFormat.parser().merge() will have the following error:

{message=Hello thinkerou, address=BeiJing}
Sep 28, 2018 2:50:16 PM com.github.thinkerou.demo.helloworld.HelloWorldClient againGreet
警告: JsonFormat parse failed: {}
com.google.protobuf.InvalidProtocolBufferException: com.google.gson.stream.MalformedJsonException: Unterminated object at line 1 column 17 path $.message
        at com.google.protobuf.util.JsonFormat$ParserImpl.merge(JsonFormat.java:1195)
        at com.google.protobuf.util.JsonFormat$Parser.merge(JsonFormat.java:370)
        at com.github.thinkerou.demo.helloworld.HelloWorldClient.againGreet(HelloWorldClient.java:92)
        at jdk.nashorn.internal.scripts.Script$10$\^eval\_.:program(<eval>:1)
        at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:637)
        at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:494)
        at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:393)
        at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:449)
        at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:406)
        at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:402)
        at jdk.nashorn.api.scripting.NashornScriptEngine.eval(NashornScriptEngine.java:155)
        at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:233)
        at com.intuit.karate.ScriptBindings.eval(ScriptBindings.java:139)
        at com.intuit.karate.ScriptBindings.updateBindingsAndEval(ScriptBindings.java:134)
        at com.intuit.karate.ScriptBindings.evalInNashorn(ScriptBindings.java:119)
        at com.intuit.karate.Script.evalJsExpression(Script.java:371)
        at com.intuit.karate.Script.evalKarateExpression(Script.java:285)
        at com.intuit.karate.Script.evalKarateExpression(Script.java:171)
        at com.intuit.karate.Script.assign(Script.java:601)
        at com.intuit.karate.Script.assign(Script.java:527)
        at com.intuit.karate.StepDefs.def(StepDefs.java:309)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at cucumber.runtime.Utils$1.call(Utils.java:40)
        at cucumber.runtime.Timeout.timeout(Timeout.java:16)
        at cucumber.runtime.Utils.invoke(Utils.java:34)
        at cucumber.runtime.java.JavaStepDefinition.execute(JavaStepDefinition.java:38)
        at cucumber.runtime.StepDefinitionMatch.runStep(StepDefinitionMatch.java:37)
        at com.intuit.karate.cucumber.CucumberUtils.runStep(CucumberUtils.java:201)
        at com.intuit.karate.cucumber.KarateRuntime.runStep(KarateRuntime.java:86)
        at cucumber.runtime.model.StepContainer.runStep(StepContainer.java:44)
        at cucumber.runtime.model.StepContainer.runSteps(StepContainer.java:39)
        at cucumber.runtime.model.CucumberScenario.run(CucumberScenario.java:44)
        at cucumber.runtime.junit.ExecutionUnitRunner.run(ExecutionUnitRunner.java:102)
        at cucumber.runtime.junit.FeatureRunner.runChild(FeatureRunner.java:63)
        at cucumber.runtime.junit.FeatureRunner.runChild(FeatureRunner.java:18)
        at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
        at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
        at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
        at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
        at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
        at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
        at cucumber.runtime.junit.FeatureRunner.run(FeatureRunner.java:70)
        at com.intuit.karate.junit4.Karate.runChild(Karate.java:123)
        at com.intuit.karate.junit4.Karate.runChild(Karate.java:38)
        at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
        at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
        at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
        at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
        at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
        at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
        at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
        at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
        at com.intuit.karate.junit4.Karate.run(Karate.java:131)
        at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:53)
        at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:123)
        at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:104)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:164)
        at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:110)
        at org.apache.maven.surefire.booter.SurefireStarter.invokeProvider(SurefireStarter.java:175)
        at org.apache.maven.surefire.booter.SurefireStarter.runSuitesInProcessWhenForked(SurefireStarter.java:107)
        at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:68)

I found {message=Hello thinkerou, address=BeiJing}, if Hello thinkerou have no space, it's OK!

Not able to start server

[email protected]:~/tempprojects/karate-grpc$mvn exec:java -Dexec.mainClass=HelloWorldServer
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Detecting the operating system and CPU architecture
[INFO] ------------------------------------------------------------------------
[INFO] os.detected.name: osx
[INFO] os.detected.arch: x86_64
[INFO] os.detected.version: 10.13
[INFO] os.detected.version.major: 10
[INFO] os.detected.version.minor: 13
[INFO] os.detected.classifier: osx-x86_64
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO]
[INFO] karate-grpc-parent
[INFO] karate-grpc-core
[INFO] karate-grpc-proto
[INFO] karate-grpc-demo
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building karate-grpc-parent 0.3.1
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- exec-maven-plugin:1.6.0:java (default-cli) @ karate-grpc-parent ---
[WARNING]
java.lang.ClassNotFoundException: HelloWorldServer
    at java.net.URLClassLoader.findClass (URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass (ClassLoader.java:424)
    at java.lang.ClassLoader.loadClass (ClassLoader.java:357)
    at org.codehaus.mojo.exec.ExecJavaMojo$1.run (ExecJavaMojo.java:270)
    at java.lang.Thread.run (Thread.java:748)
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO]
[INFO] karate-grpc-parent ................................. FAILURE [  0.493 s]
[INFO] karate-grpc-core ................................... SKIPPED
[INFO] karate-grpc-proto .................................. SKIPPED
[INFO] karate-grpc-demo ................................... SKIPPED
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.287 s
[INFO] Finished at: 2018-09-27T11:16:08+05:30
[INFO] Final Memory: 9M/155M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.codehaus.mojo:exec-maven-plugin:1.6.0:java (default-cli) on project karate-grpc-parent: An exception occured while executing the Java class. HelloWorldServer -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException

Creation of the Public grpc client failing

Hi @thinkerou ,

I am trying to start run a dummy grpc client using the following command:
java -cp .:gson.jar:grpc-netty.jar:grpc-protobuf.jar:grpc-stub.jar:protobuf-java-util.jar:karate-grpc-core.jar:karate.jar: com.intuit.karate.netty.Main find . -name 'helloworld.feature'

This includes the karate-grpc-core and its dependencies. This makes a call into the Java Interop but fails while the public client.

The grpc server is running on a privatye IP and the code snippet is attached for your reference:

Feature: grpc helloworld example
Background:
* def Client = Java.type('com.github.thinkerou.karate.GrpcClient')
* def client = Client.create('10.223.4.142', 50051)
Scenario: do it
* def payload = read('requests/helloworld.json')
* def response = client.call('helloworld.Greeter/SayHello', payload)
* def response = JSON.parse(response)
* print response
* match response[0].message == 'Hello ALL'
* def message = response[0].message

Can you help me out here?

Could not find artifact com.github.thinkerou:karate-grpc-parent:pom:1.0.3

Hi,
I am getting the below error. Can you please help ?

➜  karate-grpc-master cd karate-grpc-helper && mvn -U exec:java -Dexec.mainClass=com.github.thinkerou.karate.helper.Main
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Detecting the operating system and CPU architecture
[INFO] ------------------------------------------------------------------------
[INFO] os.detected.name: osx
[INFO] os.detected.arch: x86_64
[INFO] os.detected.version: 10.16
[INFO] os.detected.version.major: 10
[INFO] os.detected.version.minor: 16
[INFO] os.detected.classifier: osx-x86_64
Downloading from central: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-metadata.xml
Downloading from central: https://repo.maven.apache.org/maven2/org/codehaus/mojo/maven-metadata.xml
Downloaded from central: https://repo.maven.apache.org/maven2/org/apache/maven/plugins/maven-metadata.xml (14 kB at 37 kB/s)
Downloaded from central: https://repo.maven.apache.org/maven2/org/codehaus/mojo/maven-metadata.xml (20 kB at 52 kB/s)
Downloading from central: https://repo.maven.apache.org/maven2/org/codehaus/mojo/exec-maven-plugin/maven-metadata.xml
Downloaded from central: https://repo.maven.apache.org/maven2/org/codehaus/mojo/exec-maven-plugin/maven-metadata.xml (772 B at 17 kB/s)
[INFO] 
[INFO] --------------< com.github.thinkerou:karate-grpc-helper >---------------
[INFO] Building karate-grpc-helper 1.0.3
[INFO] --------------------------------[ jar ]---------------------------------
Downloading from central: https://repo.maven.apache.org/maven2/com/github/thinkerou/karate-grpc-parent/1.0.3/karate-grpc-parent-1.0.3.pom
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  1.452 s
[INFO] Finished at: 2021-05-06T00:01:25-07:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal on project karate-grpc-helper: Could not resolve dependencies for project com.github.thinkerou:karate-grpc-helper:jar:1.0.3: Failed to collect dependencies at com.github.thinkerou:karate-grpc-core:jar:1.0.3: Failed to read artifact descriptor for com.github.thinkerou:karate-grpc-core:jar:1.0.3: Could not find artifact com.github.thinkerou:karate-grpc-parent:pom:1.0.3 in central (https://repo.maven.apache.org/maven2) -> [Help 1]
[ERROR] 
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/DependencyResolutionException

Regards
Debayan

How do I receive metadata?

In karate Rest only write responseStatus, responseHeaders... but with Karate GRPC I call a server through a "GrpcClient.java" and I only receive the body as a reply.

How do I receive metadata?

Thanks for your attention @thinkerou

Unable to consume the latest released version

Following are the steps that I am following:

  1. Create a new project using the command mvn archetype:generate
  2. After the template project has been created I am basically updating the dependencies to
<dependency>
  <groupId>com.github.thinkerou</groupId>
  <artifactId>karate-grpc-core</artifactId>
  <version>1.0.3</version>
  <scope>test</scope>		  
</dependency>

Now when I run mvn dependency:resolve I get the below error

[INFO] 
[INFO] ---------------< com.rationaleemotions:code_playground >----------------
[INFO] Building code_playground 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
Downloading from central: https://repo.maven.apache.org/maven2/com/github/thinkerou/karate-grpc-parent/1.0.3/karate-grpc-parent-1.0.3.pom
Downloading from central: https://repo.maven.apache.org/maven2/junit/junit/4.11/junit-4.11.pom
Downloaded from central: https://repo.maven.apache.org/maven2/junit/junit/4.11/junit-4.11.pom (2.3 kB at 4.8 kB/s)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  12.783 s
[INFO] Finished at: 2021-10-26T17:21:18+05:30
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal on project code_playground: Could not resolve dependencies for project com.rationaleemotions:code_playground:jar:1.0-SNAPSHOT: Failed to collect dependencies at com.github.thinkerou:karate-grpc-core:jar:1.0.3: Failed to read artifact descriptor for com.github.thinkerou:karate-grpc-core:jar:1.0.3: Could not find artifact com.github.thinkerou:karate-grpc-parent:pom:1.0.3 in central (https://repo.maven.apache.org/maven2) -> [Help 1]
[ERROR] 

It looks like there's something wrong with the publishing of the grpc-parent pom file.

I went back and checked https://repo1.maven.org/maven2/com/github/thinkerou/karate-grpc-parent/ and noticed that 1.0.3 does not exist there.

Would this need a new release to get this sorted out ? Or maybe just attempt a release for 1.0.3 karate-grpc-parent alone ? Basically re-run the release job, so that it passes for the parent-pom but fails for everything else since those versions are already there?

Enable support to find protobin files from jars

The current implementation of this library basically expects to find the .protobin in the file system. This is fine if the number of proto files are less, but when this count starts increasing the code generator which translates .proto to .java basically takes a lot of time and as such one would want these to be part of a separate Maven/Gradle module, which comes in as a dependency.

Now the problem here is that karate-grpc is not aware of the .protobin that can be embedded in the proto jar.

I have solved this in an internal fork of this codebase, but I was wondering if you are open to basically accomodating that here so that I dont have to maintain my own copy.

@thinkerou - Let me know what you think and I can try and raise a PR that enables this support.

karate-grpc maintained

Is this still maintained? I was using karate for api testing but now I need something to test grpc aswell

Run test error

when run test it errors using the command:

$ mvn clean compile package -Dmaven.test.skip=true 
$ cd karate-grpc-demo
$ mvn test

error info:

grpc java.lang.NoSuchMethodError: com.google.common.base.Preconditions.checkArgument(ZLjava/lang/String;CLjava/lang/Object;)V

getting Read descriptor path failed

org.graalvm.polyglot.PolyglotException: Read descriptor path failed: /Users/rahulnautiyal/Documents/target/generated-resources/protobuf/descriptor-sets/karate-grpc.protobin

  • com.github.thinkerou.karate.service.GrpcCall.excute(GrpcCall.java:79)
  • com.github.thinkerou.karate.service.GrpcCall.invoke(GrpcCall.java:56)
  • com.github.thinkerou.karate.GrpcClient.call(GrpcClient.java:45)
  • .:program(Unnamed:1)

anything to resolve it

pom structure


com.intuit.karate
karate-junit5
${karate.version}
test

    <dependency>
        <groupId>com.github.thinkerou</groupId>
        <artifactId>karate-grpc-core</artifactId>
        <version>1.0.1</version>
    </dependency>

    <dependency>
        <groupId>com.github.thinkerou</groupId>
        <artifactId>karate-grpc-proto</artifactId>
        <version>1.0.1</version>
    </dependency>
    <dependency>
    <groupId>com.google.protobuf</groupId>
    <artifactId>protobuf-java</artifactId>
    <version>3.2.0</version>
    </dependency>
</dependencies>

<build>
    <testResources>
        <testResource>
            <directory>src/test/java</directory>
            <excludes>
                <exclude>**/*.java</exclude>
            </excludes>
        </testResource>
    </testResources>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>${maven.compiler.version}</version>
            <configuration>
                <encoding>UTF-8</encoding>
                <source>${java.version}</source>
                <target>${java.version}</target>
                <compilerArgument>-Werror</compilerArgument>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>${maven.surefire.version}</version>
            <configuration>
                <argLine>-Dfile.encoding=UTF-8</argLine>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.xolstice.maven.plugins</groupId>
            <artifactId>protobuf-maven-plugin</artifactId>
            <version>0.5.0</version>
            <configuration>
                <protocArtifact>com.google.protobuf:protoc:3.5.1</protocArtifact>
                <pluginId>grpc-java</pluginId>
                <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.12.0</pluginArtifact>
                <writeDescriptorSet>true</writeDescriptorSet>
                <descriptorSetFileName>karate-grpc.protobin</descriptorSetFileName>
                <descriptorSetOutputDirectory>${user.home}/.karate-grpc/protobuf-descriptor-sets/</descriptorSetOutputDirectory>
                <protoSourceRoot>${project.basedir}/java/proto</protoSourceRoot>
            </configuration>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>compile</goal>
                        <goal>compile-custom</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>kr.motd.maven</groupId>
            <artifactId>os-maven-plugin</artifactId>
            <version>1.6.1</version>
            <executions>
                <execution>
                    <phase>initialize</phase>
                    <goals>
                        <goal>detect</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>

Can't extract full service from the java class

Hi @thinkerou,
I have switched to maven environment and am running a grpc server locally. I have compiled the proto files and stored them in the same package as the feature files, but while trying to run the test, during the call step it says that javascript evaluation failed with the following error, could you help out the right way to mention the service name?
Call command:
* def response = client.call('github.com.Juniper.contrail.pkg.services.DiscoverResourceExecute', template_request)

Error:
com.intuit.karate.exception.KarateException: dms_api_test.feature:13 - javascript evaluation failed: client.call('github.com.Juniper.contrail.pkg.services.DiscoverResourceExecute', template_request), Can't extract full service from github.com.Juniper.contrail.pkg.services.DiscoverResourceExecute
Regards

While starting managed channels on client we get error: `Channel for target was not shutdown properly!!!`

When run bi-stream.feature case I get the follow error:

Oct 10, 2018 11:15:36 AM io.grpc.internal.ManagedChannelOrphanWrapper$ManagedChannelReference cleanQueue
严重: *~*~*~ Channel ManagedChannelImpl{logId=4, target=localhost:50051} was not shutdown properly!!! ~*~*~*
    Make sure to call shutdown()/shutdownNow() and wait until awaitTermination() returns true.
java.lang.RuntimeException: ManagedChannel allocation site
        at io.grpc.internal.ManagedChannelOrphanWrapper$ManagedChannelReference.<init>(ManagedChannelOrphanWrapper.java:103)
        at io.grpc.internal.ManagedChannelOrphanWrapper.<init>(ManagedChannelOrphanWrapper.java:53)
        at io.grpc.internal.ManagedChannelOrphanWrapper.<init>(ManagedChannelOrphanWrapper.java:44)
        at io.grpc.internal.AbstractManagedChannelImplBuilder.build(AbstractManagedChannelImplBuilder.java:410)
        at com.github.thinkerou.karate.grpc.ChannelFactory.create(ChannelFactory.java:15)
        at com.github.thinkerou.karate.service.GrpcCall.<init>(GrpcCall.java:51)
        at com.github.thinkerou.karate.service.GrpcCall.create(GrpcCall.java:47)
        at com.github.thinkerou.karate.GrpcClient.create(GrpcClient.java:24)
        at jdk.nashorn.internal.scripts.Script$8$\^eval\_.:program(<eval>:1)
        at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:637)
        at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:494)
        at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:393)
        at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:449)
        at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:406)
        at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:402)
        at jdk.nashorn.api.scripting.NashornScriptEngine.eval(NashornScriptEngine.java:155)
        at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:233)
        at com.intuit.karate.ScriptBindings.eval(ScriptBindings.java:139)
        at com.intuit.karate.ScriptBindings.updateBindingsAndEval(ScriptBindings.java:134)
        at com.intuit.karate.ScriptBindings.evalInNashorn(ScriptBindings.java:119)
        at com.intuit.karate.Script.evalJsExpression(Script.java:371)
        at com.intuit.karate.Script.evalKarateExpression(Script.java:285)
        at com.intuit.karate.Script.evalKarateExpression(Script.java:171)
        at com.intuit.karate.Script.assign(Script.java:601)
        at com.intuit.karate.Script.assign(Script.java:527)
        at com.intuit.karate.StepDefs.def(StepDefs.java:309)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at cucumber.runtime.Utils$1.call(Utils.java:40)
        at cucumber.runtime.Timeout.timeout(Timeout.java:16)
        at cucumber.runtime.Utils.invoke(Utils.java:34)
        at cucumber.runtime.java.JavaStepDefinition.execute(JavaStepDefinition.java:38)
        at cucumber.runtime.StepDefinitionMatch.runStep(StepDefinitionMatch.java:37)
        at com.intuit.karate.cucumber.CucumberUtils.runStep(CucumberUtils.java:201)
        at com.intuit.karate.cucumber.KarateRuntime.runStep(KarateRuntime.java:86)
        at cucumber.runtime.model.StepContainer.runStep(StepContainer.java:44)
        at cucumber.runtime.model.StepContainer.runSteps(StepContainer.java:39)
        at cucumber.runtime.model.CucumberScenario.runBackground(CucumberScenario.java:59)
        at cucumber.runtime.model.CucumberScenario.run(CucumberScenario.java:42)
        at cucumber.runtime.model.CucumberFeature.run(CucumberFeature.java:165)
        at com.intuit.karate.cucumber.CucumberRunner.lambda$parallel$0(CucumberRunner.java:101)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)

Oct 10, 2018 11:15:36 AM io.grpc.internal.ManagedChannelOrphanWrapper$ManagedChannelReference cleanQueue
严重: *~*~*~ Channel ManagedChannelImpl{logId=7, target=localhost:50051} was not shutdown properly!!! ~*~*~*
    Make sure to call shutdown()/shutdownNow() and wait until awaitTermination() returns true.
java.lang.RuntimeException: ManagedChannel allocation site
        at io.grpc.internal.ManagedChannelOrphanWrapper$ManagedChannelReference.<init>(ManagedChannelOrphanWrapper.java:103)
        at io.grpc.internal.ManagedChannelOrphanWrapper.<init>(ManagedChannelOrphanWrapper.java:53)
        at io.grpc.internal.ManagedChannelOrphanWrapper.<init>(ManagedChannelOrphanWrapper.java:44)
        at io.grpc.internal.AbstractManagedChannelImplBuilder.build(AbstractManagedChannelImplBuilder.java:410)
        at com.github.thinkerou.karate.grpc.ChannelFactory.create(ChannelFactory.java:15)
        at com.github.thinkerou.karate.service.GrpcCall.<init>(GrpcCall.java:51)
        at com.github.thinkerou.karate.service.GrpcCall.create(GrpcCall.java:47)
        at com.github.thinkerou.karate.GrpcClient.create(GrpcClient.java:24)
        at jdk.nashorn.internal.scripts.Script$8$\^eval\_.:program(<eval>:1)
        at jdk.nashorn.internal.runtime.ScriptFunctionData.invoke(ScriptFunctionData.java:637)
        at jdk.nashorn.internal.runtime.ScriptFunction.invoke(ScriptFunction.java:494)
        at jdk.nashorn.internal.runtime.ScriptRuntime.apply(ScriptRuntime.java:393)
        at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:449)
        at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:406)
        at jdk.nashorn.api.scripting.NashornScriptEngine.evalImpl(NashornScriptEngine.java:402)
        at jdk.nashorn.api.scripting.NashornScriptEngine.eval(NashornScriptEngine.java:155)
        at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:233)
        at com.intuit.karate.ScriptBindings.eval(ScriptBindings.java:139)
        at com.intuit.karate.ScriptBindings.updateBindingsAndEval(ScriptBindings.java:134)
        at com.intuit.karate.ScriptBindings.evalInNashorn(ScriptBindings.java:119)
        at com.intuit.karate.Script.evalJsExpression(Script.java:371)
        at com.intuit.karate.Script.evalKarateExpression(Script.java:285)
        at com.intuit.karate.Script.evalKarateExpression(Script.java:171)
        at com.intuit.karate.Script.assign(Script.java:601)
        at com.intuit.karate.Script.assign(Script.java:527)
        at com.intuit.karate.StepDefs.def(StepDefs.java:309)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at cucumber.runtime.Utils$1.call(Utils.java:40)
        at cucumber.runtime.Timeout.timeout(Timeout.java:16)
        at cucumber.runtime.Utils.invoke(Utils.java:34)
        at cucumber.runtime.java.JavaStepDefinition.execute(JavaStepDefinition.java:38)
        at cucumber.runtime.StepDefinitionMatch.runStep(StepDefinitionMatch.java:37)
        at com.intuit.karate.cucumber.CucumberUtils.runStep(CucumberUtils.java:201)
        at com.intuit.karate.cucumber.KarateRuntime.runStep(KarateRuntime.java:86)
        at cucumber.runtime.model.StepContainer.runStep(StepContainer.java:44)
        at cucumber.runtime.model.StepContainer.runSteps(StepContainer.java:39)
        at cucumber.runtime.model.CucumberScenario.runBackground(CucumberScenario.java:59)
        at cucumber.runtime.model.CucumberScenario.run(CucumberScenario.java:42)
        at cucumber.runtime.model.CucumberFeature.run(CucumberFeature.java:165)
        at com.intuit.karate.cucumber.CucumberRunner.lambda$parallel$0(CucumberRunner.java:101)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)

Google proto import issues

Hello @thinkerou

I have a proto file which imports Google proto, These were added so that it Grpc can also be hosted as REST endpoints. Though highly unnecessary, it remains in our proto file.

So I cannot use these proto files directly, Can you see if we can have this generate code for karate-grpc automation.

syntax = "proto3";

package myproto;

import "google/api/annotations.proto";


service myservice {
    rpc AnewServiee (MyRequest) returns (MyResponse) {
        option (google.api.http) = {
      post: "/mygrpcrest/AnewServiee"
      body: "*"
    };
    }
}


    message MyRequest {
        string id = 1;
    }

    message MyResponse {
        string id = 1;
        string title = 2;
        string parentId = 3;
    }
$mvn compile
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Detecting the operating system and CPU architecture
[INFO] ------------------------------------------------------------------------
[INFO] os.detected.name: osx
[INFO] os.detected.arch: x86_64
[INFO] os.detected.version: 10.14
[INFO] os.detected.version.major: 10
[INFO] os.detected.version.minor: 14
[INFO] os.detected.classifier: osx-x86_64
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building api-bdd 1.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- protobuf-maven-plugin:0.5.1:compile (default) @ api-bdd ---
[INFO] Will write descriptor set:
[INFO]  /karate-grpc/target/generated-resources/protobuf/descriptor-sets/karate-grpc.protobin
[INFO] Compiling 9 proto file(s) to /karate-grpc/target/generated-sources/protobuf/java
[ERROR] PROTOC FAILED: google/api/annotations.proto: File not found.
project/protos/Experiment.proto: Import "google/api/annotations.proto" was not found or had errors.

[ERROR] /karate-grpc/src/test/java/projects/project/protos/Experiment.proto [0:0]: google/api/annotations.proto: File not found.
project/protos/Experiment.proto: Import "google/api/annotations.proto" was not found or had errors.

[ERROR] /karate-grpc/src/test/java/projects/project/protos/category.proto [0:0]: google/api/annotations.proto: File not found.
project/protos/Experiment.proto: Import "google/api/annotations.proto" was not found or had errors.

[ERROR] /karate-grpc/src/test/java/projects/project/protos/filter.proto [0:0]: google/api/annotations.proto: File not found.
project/protos/Experiment.proto: Import "google/api/annotations.proto" was not found or had errors.

[ERROR] /karate-grpc/src/test/java/projects/project/protos/product.proto [0:0]: google/api/annotations.proto: File not found.
project/protos/Experiment.proto: Import "google/api/annotations.proto" was not found or had errors.

[ERROR] /karate-grpc/src/test/java/projects/project/protos/tax.proto [0:0]: google/api/annotations.proto: File not found.
project/protos/Experiment.proto: Import "google/api/annotations.proto" was not found or had errors.

[ERROR] /karate-grpc/src/test/java/projects/project/protos/item.proto [0:0]: google/api/annotations.proto: File not found.
project/protos/Experiment.proto: Import "google/api/annotations.proto" was not found or had errors.

[ERROR] /karate-grpc/src/test/java/projects/project/protos/user.proto [0:0]: google/api/annotations.proto: File not found.
project/protos/Experiment.proto: Import "google/api/annotations.proto" was not found or had errors.

[ERROR] /karate-grpc/src/test/java/projects/examples/helloworld.proto [0:0]: google/api/annotations.proto: File not found.
project/protos/Experiment.proto: Import "google/api/annotations.proto" was not found or had errors.

[ERROR] /karate-grpc/src/test/java/projects/examples/user.proto [0:0]: google/api/annotations.proto: File not found.
project/protos/Experiment.proto: Import "google/api/annotations.proto" was not found or had errors.

[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.422 s
[INFO] Finished at: 2018-12-11T18:13:48+05:30
[INFO] Final Memory: 11M/155M
[INFO] ------------------------------------------------------------------------

java: incompatible types error on compiling helloworld

Hi @thinkerou

I am getting the following error when I try to compile your basic Helloworld package

Error:(34, 67) java: incompatible types: java.util.List<gherkin.formatter.model.Feature> cannot be converted to java.util.List<com.github.thinkerou.demo.helloworld.Feature>
Error:(71, 39) java: incompatible types: java.util.List<com.github.thinkerou.demo.helloworld.Feature> cannot be converted to java.util.List<gherkin.formatter.model.Feature>

Using SSL certificate in Karate-gRPC. Caught exception while waiting for rpc

Hi,
Thanks for sharing this implementation. I am trying to automate a gRPC service call following the example documented here. My feature file looks like below

Feature: DeterminationAPI GetTax

  Background:
    * def Client = Java.type('com.github.thinkerou.karate.GrpcClient')
    * def client = Client.create('eg-gtp-tax-engine-adapter-mvp-grpc.kmc-default.us-west-2.test.beardsley.abc.com',443)

  Scenario: do it
    * def payload = read('getTax.json')
    * def response = client.call('com.abc.tax.amounts.v1beta1.DeterminationAPI/getTax', payload)
    * def response = JSON.parse(response)
    * print response

I have included the jar file which has the .proto file of the gRPC service (e.g. com.abc.tax.amounts.v1beta1.DeterminationAPI). However, I am getting the below error.

Jun 08, 2021 12:01:51 AM com.github.thinkerou.demo.helloworld.HelloWorldServerMain start
INFO: Server started listening on 50051
00:01:51.182 [main] WARN  testing.ServerStart - Started server on port...Jun 08, 2021 12:01:51 AM com.github.thinkerou.karate.service.GrpcCall excute
WARNING: Call grpc failed, maybe you should see the follow grpc information.
Jun 08, 2021 12:01:51 AM com.github.thinkerou.karate.service.GrpcCall excute
INFO: []

com.intuit.karate.exception.KarateException: determinationAPI.feature:8 - javascript evaluation failed: client.call('com.abc.tax.amounts.v1beta1.DeterminationAPI/getTax', payload), Can't find service with name: DeterminationAPI

	at ✽.* def response = client.call('com.abc.tax.amounts.v1beta1.DeterminationAPI/getTax', payload) (determinationAPI.feature:8)


Can you please help troubleshooting this issue?

Unable to run karate-grpc - generation of protobuf descriptor sets fails

[ERROR] Failed to execute goal on project karate-grpc-helper: Could not resolve dependencies for project com.github.thinkerou:karate-grpc-helper:jar:1.0.3: Failed to collect dependencies at com.github.thinkerou:karate-grpc-core:jar:1.0.3: Failed to read artifact descriptor for com.github.thinkerou:karate-grpc-core:jar:1.0.3: Could not find artifact com.github.thinkerou:karate-grpc-parent:pom:1.0.3 in central (https://repo.maven.apache.org/maven2) -> [Help 1]

https://repo.maven.apache.org/maven2/com/github/thinkerou/karate-grpc-helper/1.0.3 does not exist!!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.