Mocking RESTMessageV2.execute in ATF Jasmine test causes JavaException
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
11-13-2024 11:26 AM
I'm working on creating ATF tests to unit test some script includes in a scoped application. In the script include WebServiceUtil, I have a function that handles configuring and sending a RESTMessageV2 request.
The function being tested is as follows:
_rest: function(
restMessage,
restMethod,
attrs = {},
attrsNoEscape = {},
rest
) {
if (this.debug) {
gs.info("Calling {0} {1}\nattrs: {2}\nattrsNoEscape:{3}",
restMessage,
restMethod,
(!gs.nil(attrs) ? this.json.encode(attrs) : "{}"),
(!gs.nil(attrsNoEscape) ? this.json.encode(attrsNoEscape) : "{}"));
}
if (this.debug) {
var msg = "Calling :" +
"\nrestMessage: " + restMessage +
"\nrestMethod: " + restMethod +
"\nParams: ";
Object.keys(attrs).forEach(function(key) {
msg += "\nkey: " + key + ", value: " + attrs[key];
});
msg += "\nParams No Escape: ";
Object.keys(attrsNoEscape).forEach(function(key) {
msg += "\nkey: " + key + ", value: " + attrsNoEscape[key];
});
gs.info(msg);
}
var requestBody,
responseBody,
response,
status,
jObj;
try {
// set string parameters
Object.keys(attrs).forEach((k) =>
!gs.nil(attrs[k]) ?
rest.setStringParameter(k, attrs[k]) :
null);
// set non-escaped string parameters
Object.keys(attrs).forEach((k) =>
!gs.nil(attrsNoEscape[k]) ?
rest
.setStringParameterNoEscape(k, attrsNoEscape[k]) :
null);
// set the host name
rest.setStringParameter("host",
gs.getProperty("x_###_modtrak.host"));
if (!gs.nil(this.mid)) {
rest.setMIDServer(this.mid);
}
gs.info("pre-execute");
response = rest.execute();
gs.info("post-execute");
responseBody = response.getBody();
gs.info("post-getBody, pre-getStatusCode");
status = response.getStatusCode();
gs.info("got status code");
jObj = this.json.decode(responseBody);
} catch (ex) {
var err = "There was an internal error when attempting to contact ";
err += "The ModTrak REST Service: " + restMessage + ":" + restMethod;
err += "\nError: " + ex;
err += "\nError Exception: " + ex;
if (!gs.nil(response)) {
err += "\nREST Error Code: " + response.getErrorCode();
err += "\nREST Error msg: " + response.getErrorMessage();
}
gs.error(err);
responseBody = !gs.nil(ex) ? ex :
response.getErrorMessage();
return {
error: true,
errorMessage: responseBody
};
} finally {
requestBody = rest ? rest.getRequestBody() : "";
}
if (this.debug) {
gs.info("REST Message Response:" +
"\nMessage: " + restMessage +
"\nFunction: " + restMethod +
"\nStatus: " + status +
"\nRequestBody: " + requestBody +
"\nResponseBody: " + responseBody);
}
return {
error: (status != "200"),
errorMessage: (status == "200" ? "" : responseBody),
status: status,
result: jObj
};
},
In the ATF Test, I want to mock out the rest.execute() method so that we are not actually making calls to external services. I have created the following ATF test to try it out:
(function(outputs, steps, params, stepResult, assertEqual) {
describe("WebServiceUtil Script Include Tests", function() {
it('Should return the ModTrak number if everything goes correctly', function() {
var restMock = new sn_ws.RESTMessageV2(
ModTrakAPI.CONSTANTS.API.CREATE.name,
ModTrakAPI.CONSTANTS.API.CREATE.method
);
var mockResponse = {
getBody: function() {
return "12345";
},
getStatusCode: function() {
return 200;
}
};
spyOn(restMock, "execute").and.returnValue(mockResponse);
var script = new x_###_modtrak.WebServiceUtil(null, true);
var response = script._rest(
ModTrakAPI.CONSTANTS.API.CREATE.name,
ModTrakAPI.CONSTANTS.API.CREATE.method, {}, {},
restMock
);
expect(restMock.execute).toHaveBeenCalled();
expect(response.modtrak_number).toBe("12345");
});
});
})(outputs, steps, params, stepResult, assertEqual);
jasmine.getEnv().execute();
According to the SN Docs and Jasmine documentation, this implementation should not call the execute() method on RESTMessageV2, and instead return the mock response object I have configured, but instead when the test runs, when the rest.execute() method is called the following error is thrown:
Error: JavaException: java.lang.SecurityException: Method returned an object of type InterpretedFunction which is not allowed in scope x_###_modtrak
I have created a HI ticket for this but they are dismissing it as custom code. Has anyone had any luck trying to do the same?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
11-13-2024 01:24 PM
Any idea what kind of permissions that would be? The code works when tested manually, the call is made and we get a response. It's just when I try to mock out the execute function the error appears.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
11-14-2024 09:34 AM
I was able to accomplish my goal by using a helper function to wrap the execute method. Updated code and tests as follows:
Script Include Code:
rest: function(
restMessage,
restMethod,
attrs = {},
attrsNoEscape = {}
) {
if (gs.nil(restMessage) || gs.nil(restMethod)) {
gs.error("restMessage and restMethod are required");
return {
error: true,
errorMessage: "restMessage and restMethod are required"
};
}
if (this.debug) {
gs.info("Calling {0} {1}\nattrs: {2}\nattrsNoEscape:{3}",
restMessage,
restMethod,
(!gs.nil(attrs) ? this.json.encode(attrs) : "{}"),
(!gs.nil(attrsNoEscape) ? this.json.encode(attrsNoEscape) : "{}"));
}
if (this.debug) {
var msg = "Calling :" +
"\nrestMessage: " + restMessage +
"\nrestMethod: " + restMethod +
"\nParams: ";
Object.keys(attrs).forEach(function(key) {
msg += "\nkey: " + key + ", value: " + attrs[key];
});
msg += "\nParams No Escape: ";
Object.keys(attrsNoEscape).forEach(function(key) {
msg += "\nkey: " + key + ", value: " + attrsNoEscape[key];
});
gs.info(msg);
}
var requestBody,
responseBody,
response,
status,
jObj;
try {
rest = new sn_ws.RESTMessageV2(restMessage, restMethod);
// set string parameters
Object.keys(attrs).forEach((k) =>
!gs.nil(attrs[k]) ?
rest.setStringParameter(k, attrs[k]) :
null);
// set non-escaped string parameters
Object.keys(attrs).forEach((k) =>
!gs.nil(attrsNoEscape[k]) ?
rest
.setStringParameterNoEscape(k, attrsNoEscape[k]) :
null);
// set the host name
rest.setStringParameter("host",
gs.getProperty("x_###_modtrak.host"));
if (!gs.nil(this.mid)) {
rest.setMIDServer(this.mid);
}
response = this._execute(rest);
responseBody = response.getBody();
status = response.getStatusCode();
jObj = this.json.decode(responseBody);
} catch (ex) {
var err = "There was an internal error when attempting to contact ";
err += "The ModTrak REST Service: " + restMessage + ":" + restMethod;
err += "\nError: " + ex;
err += "\nError Exception: " + ex;
if (!gs.nil(response)) {
err += "\nREST Error Code: " + response.getErrorCode();
err += "\nREST Error msg: " + response.getErrorMessage();
}
gs.error(err);
responseBody = !gs.nil(ex) ? ex :
response.getErrorMessage();
return {
error: true,
errorMessage: responseBody
};
} finally {
requestBody = rest ? rest.getRequestBody() : "";
}
if (this.debug) {
gs.info("Workday REST Message Response:" +
"\nMessage: " + restMessage +
"\nFunction: " + restMethod +
"\nStatus: " + status +
"\nRequestBody: " + requestBody +
"\nResponseBody: " + responseBody);
}
return {
error: (status != "200"),
errorMessage: (status == "200" ? "" : responseBody),
status: status,
result: jObj
};
},
/**
* Internal method to enable unit testing
*/
_execute: function(request) {
return request.execute();
},
Automated Test Scripts:
(function(outputs, steps, params, stepResult, assertEqual) {
describe("WebServiceUtil Script Include Tests", function() {
it('Should return the ModTrak number if everything goes correctly', function() {
var mockResponse = {
getBody: function() {
return "12345";
},
getStatusCode: function() {
return 200;
}
};
var script = new x_###_modtrak.WebServiceUtil(null, true);
var spy = spyOn(script, "_execute");
spy.and.returnValue(mockResponse);
var response = script.rest(
ModTrakAPI.CONSTANTS.API.CREATE.name,
ModTrakAPI.CONSTANTS.API.CREATE.method, {}, {}
);
expect(spy).toHaveBeenCalled();
expect(response.result).toBe(12345);
expect(response.error).toBe(false);
expect(response.errorMessage).toBe("");
});
});
})(outputs, steps, params, stepResult, assertEqual);
// uncomment the next line to execute this script as a jasmine test
jasmine.getEnv().execute();