How to test gRPC APIs? - testing

I have been assigned to test a gRPC API (written in Golang) but I don't know how to go about testing it and I couldn't find any tutorials online for this type of testing. The only method that I can think of is to write unit tests to test the methods themselves but I would like to also test it with a client. For example, I have tested REST APIs in the past using JMeter as a client to send requests and verify the response data. Is there a method for testing gRPC APIs with a client or is unit testing the only way?

Well, I was in search for a client like Postman, then i found bloomrpc, which helps in calling grpc services. But i am not sure if it serves your purpose, if you are looking for a tool like jmeter.

If you are searching for a tool like Postman, there is also https://kreya.app. With it, you can call your gRPC services and view the responses.
Disclaimer: I'm one of the authors of Kreya.

Since you mentiond you've done testing before with JMeter, I assume that you're looking for an external test client that can call the gRPC service. There are several that you can use. The common ones are
BloomRPC
Kreya
Wombat
Fint
With those 4 clients, you can dynamically call gRPC services. However, if you are looking a test client that can also do load testing, Fint is the one you will need.

There can be two type of testing.
Testing just the implementation of the gRPC method by ignoring the networking
this question answers this aspect of the testing. By just writing the unit test for the RPC method
If you want to test both the implementation and the gRPC networking aspects as well then you need write the gRPC client for the service you want to test.
Here a code snippet about creating a gRPC client
// Set up a connection to the server.
conn, err := grpc.Dial(address, grpc.WithInsecure())
// Execute RPC you want to test
r, err := c.SayHello(context.Background(), &pb.HelloRequest{Name: name})
Check here for complete code example

Postman just published they have grpc in beta :
https://blog.postman.com/postman-now-supports-grpc/
I tested it just now and it worked perfectly for me 👍🏻🙂

You can also try this command line tool, evans, for testing gRPC

For anyone who stumbles upon this thread ...
All the previous answers have already provided good tools. We used BloomRPC & Kreya in our team (individual choices).
What I want to add is this gRPC Ecosystem Page. It contains a curated lists of all related tools. There are other GUI test tools (see GUI section), or Load testing, benchmarking tools (Testing)
https://github.com/grpc-ecosystem/awesome-grpc
PS : I'll be honest, I have not able to check all tools besides BloomRPC & Kreya.

Related

I have a Master API exposed which calls microservice A and A then called a third party microservice B. I want to mock Service B [duplicate]

I am exploring Karate API double (mocking) for the integration test. For the below scenarios, I'm not getting the expected mocking response. Your help will be appreciated.
My Setup :
1. Karate Mock Server up with pathMatches rules on port 8001: http://localhost:8001 ( working, validated against "/cat" and some test calls)
2. My own Application is up from docker on port 8080. From Docker exposed 8001 port as well.
Mocking Case:
1. My application REST call exposed to all users http://localhost:8080/service/v1/findUser. This exposed API, underlying calling other REST call http://dev-STG/userservice/v1/findUser which actually giving JSON response. So, I want to mock underlying API call and validate my API behavior accordingly.
Steps tried:
1. Now, in my application config, m replacing actual underlying API call to Karate mock server(http://localhost:8001/userservice/v1/findUser). Then did build & up my application docker.
In Karate, I defined test e.g "testIntgrtn.feature" which calling my application API "http://localhost:8080/service/v1/findUser" and Karate mock server up and set with pathmatch "/userservice/v1/findUser".
After executing "testIntgrtn.feature" karate not mocking for an underlying call(http://localhost:8001/userservice/v1/findUser).
Now, in "testIntgrtn.feature" file I changed my-application URL to underlying REST URL i.e (http://localhost:8001/userservice/v1/findUser) then mocking will work like charm.
I'm not understanding why underlying API call not getting mocked here? Did I miss something here?
Also, in Karate can we monitor all REST calls (like cypress mocking).
Thanks for this wonderful framework. Which is intuitive for writing automation cases.
Karate cannot automatically intercept calls.
The recommended approach is when you boot the application running at localhost:8080 you change the configuration so that instead of calling http://dev-stg/userservice/v1/findUser it calls something like http://localhost:8001/v1/findUser. This is what most teams do, and is easy because you should anyway be defining external URL-s as application.properties (or equivalent) as a best-practice.
It is very easy to over-ride an application property in Spring Boot for example, you can do this via the command-line: https://stackoverflow.com/a/37053004/143475
If you want, you can dynamically provision a port for the mock. So your unit test can first start a mock, get the port, and then start the server. You can find details in the Karate documentation.
All this said, if you are able to change the (system) HTTP proxy before the app at localhost:8080 starts, you may be able to do this without modifying the configuration. (But it is tricky, so I recommend the approach explained above.) So in this case, Karate can actually "intercept" the outgoing HTTP calls that the app at localhost:8080 makes.
See the second-last row (5a) in the table here: https://github.com/intuit/karate/tree/master/karate-netty#consumer-provider-example

In Karate API mocking not working as expected for me

I am exploring Karate API double (mocking) for the integration test. For the below scenarios, I'm not getting the expected mocking response. Your help will be appreciated.
My Setup :
1. Karate Mock Server up with pathMatches rules on port 8001: http://localhost:8001 ( working, validated against "/cat" and some test calls)
2. My own Application is up from docker on port 8080. From Docker exposed 8001 port as well.
Mocking Case:
1. My application REST call exposed to all users http://localhost:8080/service/v1/findUser. This exposed API, underlying calling other REST call http://dev-STG/userservice/v1/findUser which actually giving JSON response. So, I want to mock underlying API call and validate my API behavior accordingly.
Steps tried:
1. Now, in my application config, m replacing actual underlying API call to Karate mock server(http://localhost:8001/userservice/v1/findUser). Then did build & up my application docker.
In Karate, I defined test e.g "testIntgrtn.feature" which calling my application API "http://localhost:8080/service/v1/findUser" and Karate mock server up and set with pathmatch "/userservice/v1/findUser".
After executing "testIntgrtn.feature" karate not mocking for an underlying call(http://localhost:8001/userservice/v1/findUser).
Now, in "testIntgrtn.feature" file I changed my-application URL to underlying REST URL i.e (http://localhost:8001/userservice/v1/findUser) then mocking will work like charm.
I'm not understanding why underlying API call not getting mocked here? Did I miss something here?
Also, in Karate can we monitor all REST calls (like cypress mocking).
Thanks for this wonderful framework. Which is intuitive for writing automation cases.
Karate cannot automatically intercept calls.
The recommended approach is when you boot the application running at localhost:8080 you change the configuration so that instead of calling http://dev-stg/userservice/v1/findUser it calls something like http://localhost:8001/v1/findUser. This is what most teams do, and is easy because you should anyway be defining external URL-s as application.properties (or equivalent) as a best-practice.
It is very easy to over-ride an application property in Spring Boot for example, you can do this via the command-line: https://stackoverflow.com/a/37053004/143475
If you want, you can dynamically provision a port for the mock. So your unit test can first start a mock, get the port, and then start the server. You can find details in the Karate documentation.
All this said, if you are able to change the (system) HTTP proxy before the app at localhost:8080 starts, you may be able to do this without modifying the configuration. (But it is tricky, so I recommend the approach explained above.) So in this case, Karate can actually "intercept" the outgoing HTTP calls that the app at localhost:8080 makes.
See the second-last row (5a) in the table here: https://github.com/intuit/karate/tree/master/karate-netty#consumer-provider-example

How to test Web Services with Elixir?

We have a couple of REST APIs that need to be tested. APIs are owned by some other team. Currently, we use Node.js with Ava to test our APIs.
We have recently started exploring Elixir as our scripting language. We would like to experiment with Elixir to test REST API. The question here is - how to test external web services/REST API with Elixir?
Every Google search around Elixir testing refers back to ExUnit which is basically for unit testing of Elixir apps. We don't have any app written in Elixir or in Phoenix.
All we want to do is to test API end-to-end. How to do that with Elixir? Which libraries to use? I know I can make network calls from my tests written in ExUnit and verify the API behavior, but not sure if it is the right way.
NOTE: We already have JMeter in place for load testing of API but we wish to keep functional testing separate from load testing due to complex workflows involved with API.
I think what you descried in the answer is the right way.
You can use ExUnit as the test running and reporting framework. In ExUnit you can do whatever you want, make network calls, even parse the DOM. For testing a REST API you can use HTTPoision and assert on status code and response body.
Create a new mix project
mix new api_test
Add HTTPoison dependency to mix.exs
...
defp deps do
[
{:httpoison, "~> 1.6"}
]
end
...
Run mix deps.get to get HTTPoison installed.
Add a test in test/api_test_test.exs
defmodule ApiTestTest do
use ExUnit.Case
doctest ApiTest
test "API alive" do
resp = HTTPoison.get!("https://api.github.com")
assert resp.status_code == 200
end
end
Run the tests with mix test from the project root.

REST API Works in Browser, But Not Client

I am developing a REST API, and have found a very interesting problem.
When I access the resources in a web browser (in my case Chrome), everything works fine. However, when I access the resources using a REST client (Google Chrome plugin, web-based client, and a Java applet), NONE of the variables pass to the API. This happens both with GET and POST methods.
I have absolutely no idea why this would be the case, and it's proving very difficult to test the methods before putting them into production (especially with POST methods).
Please help!
At first glance it sounds it could be 2 things:
You are not correctly passing API parameters via your client or
applet
A problem with authentication or cookie management. Does the API require any type of authorization?
Are you forgetting to set a necessary HTTP header?
Do you have control of the API also or is it a third party API? If so, do the params arrive at all or do they arrive empty? What's the error code? - a 403 not authorized (which would make sense if the key doesn't pass) or something else due to missing params.
Try the intermediate step of doing it with CURL form the command line - that'll give you more detail on what's coming back.

Strategies to block an external webservice to simulate "down" during for a testing scenario?

I am working to integrate data from an external web service in the client side of my appliction. Someone asked me to test the condition when the service is unavailable or down. Anyone have any tips on how to block this site temporarily while we run the test to see how the service degrades?
For those curious we are testing against Virtual Earth, but Google Maps but this would apply to any equally complicated external service.
any thoughts and suggestions are welcome
Create some Mock-Webservice class or interface (and inject it). In there, you could test the response of your system to webservice failures and also what happens, if a web-service request take longer than expected or actually time-out.
DeveloperWorks article on mock testing: http://www.ibm.com/developerworks/library/j-mocktest.html
You need to be sure to test the most common failure modes for this:
DNS lookup fails
IP connection fails (once DNS lookup succeeds)
HTTP response other than 200
HTTP response incomplete or timeout
HTTP response 200 but RPC or document returned is invalid
Those are just a few common failure modes I could think of that will all manifest themselves with different behaviors that you may wish to have your application handle explicitly.
If you set up a computer between the caller and service that routes between them, you can simulate each of these failure modes distinctly and modify your application to handle them.
How about blocking the domain name(s) in question by putting a nonsense entry into the hosts file?