[FOLIO-685] explore auto-generation of fakes (mocks) for module testing Created: 20/Jun/17 Updated: 02/Sep/21 Resolved: 02/Sep/21 |
|
| Status: | Closed |
| Project: | FOLIO |
| Components: | None |
| Affects versions: | None |
| Fix versions: | None |
| Type: | Task | Priority: | P3 |
| Reporter: | Jakub Skoczen | Assignee: | shale99 |
| Resolution: | Won't Do | Votes: | 0 |
| Labels: | for-next-sprint | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original estimate: | Not Specified | ||
| Sprint: |
| Description |
|
This came up during the core meeting today. In principle we should be able to generate mock (fake) services from RAML/Schema specs (which contain example data). We suspect this is not going to be good enough for testing more specialized functionality but it might be a good starting point. So the tool could generate some boilerplate mock/fake code that the developer than could modify to fit the needs of the test. |
| Comments |
| Comment by shale99 [ 02/Jul/17 ] |
|
started looking into this initially trying to use Google's Guice framework for DI. Decided to go a simpler route for now. Prototyped locally: 1. RMB has its own http client which wraps vertx's http client - adding caching, build cql functionality, etc... example of the mock_content.json
{
"mocks": [
{
"description" : "url -> when this url is called with the method [get / put / etc...] than if the request requires input data ",
"url": "/users?query=username=joe",
"method": "get",
"status": 200,
"receivedData": {"id": "1","a31": "1"},
"receivedPath": "",
"sendData" : {},
"headers" : [
{"name": "x-okapi-token", "value": "12345"},
{"name": "x-okapi-tenant", "value": "eeee"}
]
},
{
"url": "auth_test2",
"method": "get",
"status": 200,
"receivedData" : {},
"receivedPath": "",
"sendData" : {}
}
]
}
|
| Comment by shale99 [ 03/Jul/17 ] |
|
a bit more info - the mock http service will also indicate which urls you are attempting to access and will return a mock error if you have not indicated what to return for a specific url. For example - the below is the error output when calling /bl-users?query=username=joe without having an entry in the mock_content.json for the /groups url. Note that this runs the actual mod-users-bl service - only replaces the http client with the mock http client (due to the sys property indicated at verticle startup) - the URLs in mod-users-bl (as with other biz modules) are auto generated from the json returned from the /users (or other) endpoint - so when mocking json responses - you need to be aware (or at least run the mock once to see) of which urls need to be mocked [Mon Jul 03 10:26:52 IDT 2017] org.folio.rest.tools.client.test.HttpClientMock2 INFO MOCKING URL: /users?query=username=joe&offset=0&limit=10 [Mon Jul 03 10:26:55 IDT 2017] org.folio.rest.tools.client.test.HttpClientMock2 INFO MOCKING URL: /groups?query=id==4bb563d9-3f9d-4e1e-8d1d-04e75666d68f [Mon Jul 03 10:26:57 IDT 2017] org.folio.rest.tools.client.test.HttpClientMock2 INFO MOCKING URL: /perms/users?query=username==jhandey [Mon Jul 03 10:27:01 IDT 2017] org.folio.rest.impl.BlUsersAPI SEVERE { "endpoint" : "/groups?query=id==4bb563d9-3f9d-4e1e-8d1d-04e75666d68f", "statusCode" : 0, "errorMessage" : "mocked error" } |
| Comment by shale99 [ 03/Jul/17 ] |
|
sys property to indicate mock mode: -Dmock.httpclient note that if the json passed in is large - you can place it in a separate file and then reference it relatively via the "receivedPath": "", field in the mock_content.json the headers section allows you to indicate which headers / values the endpoint will return (simulate) |
| Comment by shale99 [ 03/Jul/17 ] |
|
unit test example using mocks: start verticle in mock mode:
DeploymentOptions options = new DeploymentOptions().setConfig(new JsonObject().put("http.port",
port).put(HttpClientMock2.MOCK_MODE, "true"));
vertx.deployVerticle(RestVerticle.class.getName(), options, context.asyncAssertSuccess(id -> {
async.complete();
}));
check response returned from veritcle endpoint - internally, the endpoint will replace outgoing calls to other modules with content from the mock_content.json
CompletableFuture<Response> response = httpClient.request("/bl-users?include=perms");
response.whenComplete( (resp, ex) -> {
try {
assertEquals(200, resp.getCode());
if(resp.getError() != null){
System.out.println(resp.getError().encode());
}
async.complete();
} catch (Throwable e) {
context.fail(e.getMessage());
}
});
|
| Comment by shale99 [ 16/Jul/17 ] |
|
summary: using the sys property / vertx config property - you can indicate to the verticle which mode you are running in (regular or mock) - in case of mock mode - you create a json with an entry per url you are calling from within your module and indicate (in the json) what data , status code , and headers should be returned when that url is called - in mock mode - the request will not be sent out but the response will be constructed from the json entries |
| Comment by shale99 [ 17/Jul/17 ] |
|
Kurt Nordstrom , Marc Johnson , Jakub Skoczen - any comments on this, different implementation ideas? |
| Comment by Marc Johnson [ 18/Jul/17 ] |
|
If my understanding of this approach is sensible, the goal is to replace the HTTP client (via configuration) within a RAML-module-builder based module in order to not make requests to other interface implementations. At the moment, it appears the mock will respond to any URL defined in it's content configuration. In the future, do you envisage that the mock will be schema / RAML aware? The approach that the inventory and circulation modules have taken up until now is different, they use external fake implementations (based upon conventions at the moment) running externally to the module being tested. |
| Comment by shale99 [ 18/Jul/17 ] |
|
right, the idea behind the rmb mocks is that, based on a config you can indicate you are running in mock mode. |