- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
06-08-2017 08:01 AM
I have a function that uses sn_ws.RESTMessageV2 and I need to write a unit test for it. Is there a way to Mock the sn_ws.REST classes for testing?
I can't seem to figure out how to properly unit test a function that uses it.
Here is my function:
MyClass.prototype = {
sendRestMessage: function(method, uri, content) {
var errorMsg;
var request;
var response;
var responseBody;
request = this._createRestMessage(method, uri, content);
response = request.execute();
responseBody = this._handleRestResponse(response);
return responseBody;
},
/**
* @returns {sn_ws.RESTMessageV2} A request object
*/
_createRestMessage: function(method, uri, content) { ... },
/**
* @returns {String} The JSON String body of the response
*/
_handleRestResponse: function(response) { ... },
};
Here is a bg script I tried to use to test it:
var json = new JSON();
json.prettify();
var expectedResult;
var actualResult = {};
var server = "fakeServer";
var method = "get";
var uri = "/fake/uri";
var content = { farts: "smell bad" };
var requestBody = '{"data":"My Fake Data"}';
var myc = new MyClass(device);
myc._createRestMessage = function(x_method, x_uri, x_content) {
var request = new sn_ws.RESTMessageV2();
actualResult['_createRestMessage'] = { method:x_method, uri:x_uri, content:x_content };
request.execute = function() {
return new sn_ws.RESTResponseV2();
};
return request;
};
myc._handleRestResponse = function(x_response) {
return requestBody;
};
actualResult['result'] = f5Ctrl.sendRestMessage(method, uri, content);
gs.print(json.encodeObject(actualResult));
I am hitting an error:
Evaluator: java.lang.IllegalStateException: Bad implementaion of call as constructor, name=RESTResponseV2
Which, I assume, means that I can't create a new RESTResponseV2().
thanks in advance.
Solved! Go to Solution.
- Labels:
-
Automated Test Framework
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
08-08-2023 12:25 PM - edited 08-08-2023 12:30 PM
Well, I'm a few years late to the party, but I figured I'd put this here in case anybody else is trying to mock a rest message.
My solution was to create a class that could be extended to mock any specific REST message:
var X_MockRestMessage = Class.create();
X_MockRestMessage.prototype = Object.extendsObject(sn_ws.RESTMessageV2,{
_responseBody: undefined,
_responseCode: 200,
restResponse: global.RESTResponse,
_parentClass: sn_ws.RESTMessageV2,
/*_________________________________________________________________
* Description: Create dummy methods
* Parameters: @Array methodNames - names of the methods
@Object fn (optional) - function to set the dummy properties equal too
* Returns: @Abhijeet Singh
________________________________________________________________*/
createDummyMethods: function(methodNames,fn){
if(!fn){
fn = function(){return;};
}
for(var i in methodNames){
this[methodNames[i]] = fn;
}
},
/*_________________________________________________________________
* Description: method to override the execute method with when mocking data
eg.: this.execute = this.mockExecute;
* Parameters: n/a
* Returns: @Global.RESTECCResponse
* future - a. would be better if we could return @sn_ws.RESTResponseV2
the challenge being that it is a Java class
b. would be better design to use an interface instead of a class
________________________________________________________________*/
mockExecute: function(){
var _restResponse = Class.create();
_restResponse.prototype = Object.extendsObject(global.RESTECCResponse);
_restResponse.prototype._processEccQueueInput = function(){
return;
};
var res = new _restResponse();
res.body = this._responseBody;
res.statusCode = this._responseCode;
return res;
},
/*_________________________________________________________________
* Description: set the response body
* Parameters: @String body
* Returns: @Abhijeet Singh
________________________________________________________________*/
setResponseBody: function(body){
this._responseBody = body;
},
type: 'X_MockRestMessage'
});
Extend for specific REST message ("Some Service" in this case)
var X_MockSomeServiceRestMessage = Class.create();
X_MockSomeServiceRestMessage.prototype = Object.extendsObject(global.X_MockRestMessage,{ //extends sn_ws.RESTMessageV2
initialize: function(restMessageName,method) {
gs.info('X_MockSomeServiceRestMessage initializing');
//if this is for method "Get Report" we will mock the results
if(method == this.GET_REPORT){
gs.info('X_MockSomeServiceRestMessage setting responseBody to system property x_mock_rest_response');
//mock the response with the test date in the system property
this.setResponseBody(gs.getProperty('x_mock_rest_response'));
//override the execute method of sn_ws.RESTMessageV2 -
//call the mockExecute method of X_MockRestMessage instead
this.execute = this.mockExecute;
}
this.createDummyMethods(this.dummyMethods);
},
//method of the Some Service Rest Message that we are mocking
GET_REPORT: 'Get Report',
dummyMethods: ['setStringParameter','setRequestHeader','setLogLevel','setQueryParameter'],
//in case we need to call a parent method...
_parentClass: global.X_MockRestMessage,
type: 'X_MockSomeServiceRestMessage'
});
var X_MyClass = Class.create();
X_MyClass.prototype = {
initialize: function() {
this.restMessage = gs.getProperty('x_mock_rest_message') == 'true' ?
X_MockSomeServiceRestMessage:
sn_ws.RESTMessageV2;
},
someMethod: function() {
var myRestMessage = new this.restMessage('My REST API','My REST Method');
//etc, etc
},
type: ' X_MyClass'
};

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
06-08-2017 08:08 AM
Hi Mike,
I'm not certain I'm understanding all the details. What I can provide is how I test these.
The script include, somewhere does a call to instantiate a new sn_ws.RESTMessageV2() object, right? Whether you are using a defined outbound REST message (as an arg to the new call, or you are setting the endpoint, parameters, etc. explicity.)
That's how I construct my REST message calls inside a script include. To test it, I just write a small test script to call the method which contains the RESTMessageV2() call. If it works (e.g. creates a record) then I know I passed the test. Don't forget to also try bad cases/rainy day tests.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
06-08-2017 08:21 AM
So, sure, I could have the function reach out to the target server and do something, then go clean it up when I'm done. I could also send a 'get' which won't actually change anything. However, I'm trying to avoid that, because if the target isn't available or there is some other issue with it, then this test (as would any other similar tests) would fail. I have integration tests that will test that part and want this unit test to isolate this function.
After I posted, I realized that when my function called execute(), it wasn't doing anything with the response other than handing it off to another function, so as long as I overloaded that function as well, it didn't really matter what it returned.
In the end, this did what I needed:
var fakeResponse = Class.create();
f5Ctrl._createRestMessage = function(x_method, x_uri, x_content) {
var request = new sn_ws.RESTMessageV2();
actualResult['_createRestMessage'] = { method:x_method, uri:x_uri, content:x_content };
request.execute = function() {
return fakeResponse;
};
return request;
};
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
08-08-2023 12:25 PM - edited 08-08-2023 12:30 PM
Well, I'm a few years late to the party, but I figured I'd put this here in case anybody else is trying to mock a rest message.
My solution was to create a class that could be extended to mock any specific REST message:
var X_MockRestMessage = Class.create();
X_MockRestMessage.prototype = Object.extendsObject(sn_ws.RESTMessageV2,{
_responseBody: undefined,
_responseCode: 200,
restResponse: global.RESTResponse,
_parentClass: sn_ws.RESTMessageV2,
/*_________________________________________________________________
* Description: Create dummy methods
* Parameters: @Array methodNames - names of the methods
@Object fn (optional) - function to set the dummy properties equal too
* Returns: @Abhijeet Singh
________________________________________________________________*/
createDummyMethods: function(methodNames,fn){
if(!fn){
fn = function(){return;};
}
for(var i in methodNames){
this[methodNames[i]] = fn;
}
},
/*_________________________________________________________________
* Description: method to override the execute method with when mocking data
eg.: this.execute = this.mockExecute;
* Parameters: n/a
* Returns: @Global.RESTECCResponse
* future - a. would be better if we could return @sn_ws.RESTResponseV2
the challenge being that it is a Java class
b. would be better design to use an interface instead of a class
________________________________________________________________*/
mockExecute: function(){
var _restResponse = Class.create();
_restResponse.prototype = Object.extendsObject(global.RESTECCResponse);
_restResponse.prototype._processEccQueueInput = function(){
return;
};
var res = new _restResponse();
res.body = this._responseBody;
res.statusCode = this._responseCode;
return res;
},
/*_________________________________________________________________
* Description: set the response body
* Parameters: @String body
* Returns: @Abhijeet Singh
________________________________________________________________*/
setResponseBody: function(body){
this._responseBody = body;
},
type: 'X_MockRestMessage'
});
Extend for specific REST message ("Some Service" in this case)
var X_MockSomeServiceRestMessage = Class.create();
X_MockSomeServiceRestMessage.prototype = Object.extendsObject(global.X_MockRestMessage,{ //extends sn_ws.RESTMessageV2
initialize: function(restMessageName,method) {
gs.info('X_MockSomeServiceRestMessage initializing');
//if this is for method "Get Report" we will mock the results
if(method == this.GET_REPORT){
gs.info('X_MockSomeServiceRestMessage setting responseBody to system property x_mock_rest_response');
//mock the response with the test date in the system property
this.setResponseBody(gs.getProperty('x_mock_rest_response'));
//override the execute method of sn_ws.RESTMessageV2 -
//call the mockExecute method of X_MockRestMessage instead
this.execute = this.mockExecute;
}
this.createDummyMethods(this.dummyMethods);
},
//method of the Some Service Rest Message that we are mocking
GET_REPORT: 'Get Report',
dummyMethods: ['setStringParameter','setRequestHeader','setLogLevel','setQueryParameter'],
//in case we need to call a parent method...
_parentClass: global.X_MockRestMessage,
type: 'X_MockSomeServiceRestMessage'
});
var X_MyClass = Class.create();
X_MyClass.prototype = {
initialize: function() {
this.restMessage = gs.getProperty('x_mock_rest_message') == 'true' ?
X_MockSomeServiceRestMessage:
sn_ws.RESTMessageV2;
},
someMethod: function() {
var myRestMessage = new this.restMessage('My REST API','My REST Method');
//etc, etc
},
type: ' X_MyClass'
};