There are many testing tools available that support testing REST APIs. On this page two approaches to testing are demonstrated by testing the PingPong API.
Testing Ping Pong APU with Metaswitch Scenario Simulator
The Scenario Simulator is a testing tool which simulates network traffic — for testing network elements and services. You define your test cases with scenario definition files, which describe the message flows between network elements. The scenario simulator can play one or more roles when you run the scenario.
The following scenario file describes a call-flow where the client sends a Ping (api=SS-ClientApiToTest, scenario=SS-ClientApiTestScenarioToRun)
request to a server. The expected response is a 200 OK, with a response body of Pong!
.
ping-request [description "Triggers the example service with a pingpong api POST rest request."] (FORMAT 1.0) {
(ROLES) {
RESTCLIENT [description "client to the unified rest ra"] ;
UNIFIEDREST [description "rhino with a unified rest ra installed and activated"] ;
}
(DIALOGS) {
RESTCLIENT-UNIFIEDREST [description "rest/http interactions"] (ROLE_A RESTCLIENT, ROLE_B UNIFIEDREST, SCHEMA http, VERSION 1.0c) {
applicationContext "HTTP/1.1";
}
}
(TABLES) ;
POST (DIALOG RESTCLIENT-UNIFIEDREST, DIRECTION A_TO_B) {
Request-URI {
Encoded "/pingpong/ping";
}
headers {
Content-Length (AUTO) ;
Content-Type "application/json";
Host "localhost:8000";
}
Message-Body {
application_json_UTF-8 {
Object {
Name-Value {
Name "api";
Value {
Primitive {
String "SS-ClientApiToTest";
}
}
}
Name-Value {
Name "scenario";
Value {
Primitive {
String "SS-ClientApiTestScenarioToRun";
}
}
}
}
}
}
}
200 (DIALOG RESTCLIENT-UNIFIEDREST, DIRECTION B_TO_A) {
headers {
Content-Length (AUTO) ;
Date (AUTO) ;
}
Message-Body {
text_plain_UTF-8 "Pong!";
}
}
}
View the scenario file with the Scenario Editor. |
The scenario simulator can be used interactively to run scenarios.
~/work/unified-rest-ra-sdk/sim$ ~/scenario-sim/scenario-simulator.sh -f setup-restclient.commands
Starting JVM...
Processing commands from file at setup-restclient.commands
Processing command: set-endpoint-address rest-client-http-endpoint localhost:8181
Processing command: create-local-endpoint rest-client-http-endpoint http -propsfile setup-restclient.properties
Initializing local endpoint "rest-client-http-endpoint" ...
Local endpoint initialized.
Processing command: bind-role RESTCLIENT rest-client-http-endpoint
Processing command: set-endpoint-address unified-rest-http-endpoint localhost:8000
Processing command: bind-role UNIFIEDREST unified-rest-http-endpoint
Finished reading commands from file
Ready to start
Please type commands... (type "help" <ENTER> for command help)
> load-scenario ping-request.scen
Playing role "RESTCLIENT" in initiating scenario "ping-request" with dialogs [RESTCLIENT-UNIFIEDREST]
> run-session ping-request
Send --> POST to unified-rest-http-endpoint
Recv <-- 200 OK from unified-rest-http-endpoint
Outcome of "ping-request" session: Matched scenario definition "ping-request"
>
-
Start the scenario simulator. The argument is a file of commands to run on startup that defines all the roles involved in the scenario.
-
Load a scenario to run
-
Run the scenario and observe the results. The scenario simaulor plays the role of the client and sends a POST request to the server (the example-rest-ra in Rhino). The server (the service running in Rhino) sends a 200 OK response. This response matches the expected response in this scenario, so the test passes.
The scenario sim setup commands file used in this test
|
Here is a snippet of the Rhino logs showing what happened on the server.
[example_rest_ra.controller] incomingHttpRequest: id=HttpRequestId[incoming,6,3], request=FullHttpRequest[POST http://localhost:8000/pingpong/ping]
[example_rest_ra.controller] Select an API suitable for: '/pingpong/ping'
[example_rest_ra] startActivity: HttpActivity[nodeID=101,requestId=HttpRequestId[incoming,6,3]]
[example_rest_ra] selectApiRestRATypeProvider('/pingpong') = 'PingpongApiServerPluginRATypeProvider@6a3877a1'
[example_rest_ra] fireEvent: ah=HttpActivity[nodeID=101,requestId=HttpRequestId[incoming,6,3]], eventID=EventTypeID[name=PingRequest,vendor=ExampleCo,version=1.0], event=PingRequest[pingContext=PingContext { api: SS-ClientApiToTest, scenario: SS-ClientApiTestScenarioToRun }], address=null, flags=96
[example-rest-api-sbb] sbbCreate
[example-rest-api-sbb] sbbPostCreate
[example-pingpong-api-sbbpart] SBB part created
[example-pingpong-api-sbbpart] Received: PingRequest[pingContext=PingContext { api: SS-ClientApiToTest, scenario: SS-ClientApiTestScenarioToRun }]
[example-pingpong-api-sbbpart] Ping! PingRequest[pingContext=PingContext { api: SS-ClientApiToTest, scenario: SS-ClientApiTestScenarioToRun }]
[example-rest-api-sbb] Triggering: api=SS-ClientApiToTest, scenario=SS-ClientApiTestScenarioToRun
[example_rest_ra] sendResponse: Event: SEND_REST_RESPONSE, Type: REST_Response, API: PINGPONG, Operation: Ping, Content:
[example-rest-api-sbb] sbbStore
[example_rest_ra] eventProcessingSuccessful: ah=HttpActivity[nodeID=101,requestId=HttpRequestId[incoming,6,3]], eventID=EventTypeID[name=PingRequest,vendor=ExampleCo,version=1.0], event=PingRequest[pingContext=PingContext { api: SS-ClientApiToTest, scenario: SS-ClientApiTestScenarioToRun }], address=null, flags=256
[example-rest-api-sbb] sbbRemove
-
The example-rest-ra receives the POST REST request
-
The example-rest-ra determines which API should process this new request
-
… It is the
PingpongApiServerPluginRATypeProvider
-
The example-rest-ra creates, and fires an event to Rhino for processing by a service
-
example-rest-api-sbb (the root sbb of the example service) and example-pingpong-api-sbbpart are instantiated
-
The example-pingpong-api-sbbpart instance receives the PingRequest event.
-
… and triggers the example-rest-api-sbb, which logs some details about the Ping request.
-
The example-pingpong-api-sbbpart sends a 200 OK response
-
Rhino notifies the example-rest-ra that the PingRequest event has been processed by a service.
-
Rhino cleans up the example-rest-api-sbb instance
Learn about Rhino TAS - Telecom Application Server and JAIN SLEE (JSR 240). |
Testing Ping Pong API the with Swagger Inspector
In the following screenshot, Swagger Inspector is used to trigger the example service running in Rhino. In this case, the Swagger Inspector is playing the role of the client.
Here is a snippet of the Rhino logs showing what happened on the server.
[example-rest-api-sbb] sbbCreate
[example-rest-api-sbb] sbbPostCreate
[example-pingpong-api-sbbpart] SBB part created
[example-pingpong-api-sbbpart] Received: PingRequest[pingContext=PingContext { api: ClientApiToTest, scenario: ClientApiScenario }]
[example-pingpong-api-sbbpart] Ping! PingRequest[pingContext=PingContext { api: ClientApiToTest, scenario: ClientApiScenario }]
[example-rest-api-sbb] Triggering: api=ClientApiToTest, scenario=ClientApiScenario
[example-rest-api-sbb] sbbStore
[example-rest-api-sbb] sbbRemove
-
example-rest-api-sbb (the root sbb of the example service) and example-pingpong-api-sbbpart are instantiated
-
The example-pingpong-api-sbbpart instance receives the PingRequest event.
-
… and triggers the example-rest-api-sbb, which logs some details about the Ping request.
-
Rhino cleans up the example-rest-api-sbb instance
Testing Pet Store API with the Swagger Inspector
In the following screenshot, Swagger Inspector is used to trigger the example service running in Rhino. In this case, the Swagger Inspector is playing the role of the client.
[trace.example-rest-api-sbb] sbbCreate
[trace.example-rest-api-sbb] sbbPostCreate
[trace.example-petstore-api-sbbpart] SBB part created
[trace.example-pingpong-api-sbbpart] SBB part created
[trace.example-petstore-api-sbbpart] Received: CreatePetRequest[pet=Pet { id: 10, name: Ploppy }]
[trace.example-petstore-api-sbbpart] Added pet: Pet { id: 10, name: Ploppy }
[trace.example-rest-api-sbb] sbbStore
[trace.example-rest-api-sbb] sbbRemove
[trace.example-rest-api-sbb] sbbCreate
[trace.example-rest-api-sbb] sbbPostCreate
[trace.example-petstore-api-sbbpart] SBB part created
[trace.example-pingpong-api-sbbpart] SBB part created
[trace.example-petstore-api-sbbpart] Received: ListPetsRequest[]
[trace.example-petstore-api-sbbpart] Listing Pets: [Pet { id: 1, name: Stripey }, Pet { id: 2, name: Splodge }, Pet { id: 3, name: Simba }, Pet { id: 10, name: Ploppy }]
[trace.example-rest-api-sbb] sbbStore
[trace.example-rest-api-sbb] sbbRemove
[trace.example-rest-api-sbb] sbbCreate
[trace.example-rest-api-sbb] sbbPostCreate
[trace.example-petstore-api-sbbpart] SBB part created
[trace.example-pingpong-api-sbbpart] SBB part created
[trace.example-petstore-api-sbbpart] Received: ShowPetByIdRequest[petId=5]
[trace.example-petstore-api-sbbpart] Show pet with id: 5 = null
[trace.example-rest-api-sbb] sbbStore
[trace.example-rest-api-sbb] sbbRemove
[trace.example-rest-api-sbb] sbbCreate
[trace.example-rest-api-sbb] sbbPostCreate
[trace.example-petstore-api-sbbpart] SBB part created
[trace.example-pingpong-api-sbbpart] SBB part created
[trace.example-petstore-api-sbbpart] Received: ShowPetByIdRequest[petId=10]
[trace.example-rest-api-sbb] sbbStore
[trace.example-rest-api-sbb] sbbRemove