I have a UI5
application that I run it with UI5
standard build-in mock server for testing.
Here is the code from mockserver.js that is generate by Web IDE
automatically:
sap.ui.define([
"sap/ui/core/util/MockServer",
"sap/ui/model/json/JSONModel",
"sap/base/util/UriParameters",
"sap/base/Log"
], function (MockServer, JSONModel, UriParameters, Log) {
"use strict";
var oMockServer,
_sAppPath = "de/cimt/test/",
_sJsonFilesPath = _sAppPath + "localService/mockdata";
var oMockServerInterface = {
/**
* Initializes the mock server asynchronously.
* You can configure the delay with the URL parameter "serverDelay".
* The local mock data in this folder is returned instead of the real data for testing.
* @protected
* @param {object} [oOptionsParameter] init parameters for the mockserver
* @returns{Promise} a promise that is resolved when the mock server has been started
*/
init : function (oOptionsParameter) {
var oOptions = oOptionsParameter || {};
return new Promise(function(fnResolve, fnReject) {
var sManifestUrl = sap.ui.require.toUrl(_sAppPath + "manifest.json"),
oManifestModel = new JSONModel(sManifestUrl);
oManifestModel.attachRequestCompleted(function () {
var oUriParameters = new UriParameters(window.location.href),
// parse manifest for local metatadata URI
sJsonFilesUrl = sap.ui.require.toUrl(_sJsonFilesPath),
oMainDataSource = oManifestModel.getProperty("/sap.app/dataSources/mainService"),
sMetadataUrl = sap.ui.require.toUrl(_sAppPath + oMainDataSource.settings.localUri),
// ensure there is a trailing slash
sMockServerUrl = /.*\/$/.test(oMainDataSource.uri) ? oMainDataSource.uri : oMainDataSource.uri + "/";
// ensure the URL to be relative to the application
sMockServerUrl = sMockServerUrl && new URI(sMockServerUrl).absoluteTo(sap.ui.require.toUrl(_sAppPath)).toString();
// create a mock server instance or stop the existing one to reinitialize
if (!oMockServer) {
oMockServer = new MockServer({
rootUri: sMockServerUrl
});
} else {
oMockServer.stop();
}
// configure mock server with the given options or a default delay of 0.5s
MockServer.config({
autoRespond : true,
autoRespondAfter : (oOptions.delay || oUriParameters.get("serverDelay") || 500)
});
// simulate all requests using mock data
oMockServer.simulate(sMetadataUrl, {
sMockdataBaseUrl : sJsonFilesUrl,
bGenerateMissingMockData : true
});
var aRequests = oMockServer.getRequests();
// compose an error response for each request
var fnResponse = function (iErrCode, sMessage, aRequest) {
aRequest.response = function(oXhr){
oXhr.respond(iErrCode, {"Content-Type": "text/plain;charset=utf-8"}, sMessage);
};
};
// simulate metadata errors
if (oOptions.metadataError || oUriParameters.get("metadataError")) {
aRequests.forEach(function (aEntry) {
if (aEntry.path.toString().indexOf("$metadata") > -1) {
fnResponse(500, "metadata Error", aEntry);
}
});
}
// simulate request errors
var sErrorParam = oOptions.errorType || oUriParameters.get("errorType"),
iErrorCode = sErrorParam === "badRequest" ? 400 : 500;
if (sErrorParam) {
aRequests.forEach(function (aEntry) {
fnResponse(iErrorCode, sErrorParam, aEntry);
});
}
// custom mock behaviour may be added here
// set requests and start the server
oMockServer.setRequests(aRequests);
oMockServer.start();
Log.info("Running the app with mock data");
fnResolve();
});
oManifestModel.attachRequestFailed(function () {
var sError = "Failed to load application manifest";
Log.error(sError);
fnReject(new Error(sError));
});
});
},
/**
* @public returns the mockserver of the app, should be used in integration tests
* @returns {sap.ui.core.util.MockServer} the mockserver instance
*/
getMockServer : function () {
return oMockServer;
}
};
return oMockServerInterface;
});
All the sets in my oData metadata have the ID
of type integer! (Auto incremental in the real gateway server)
The funny part is that when I create a new object of a set, it will assign 9
as the id of that object which was created for the first time, and the second created object will be 416
and so on.
What is clear is that the build-in mock server uses a random generate algorithm without or with a static seed. That is the reason that it will generate all the time same chain of the ids for each set in my metadata model.
Now my question is how can I change this behavior of the UI5 mock server?
In the other word, how can I set a random number as the seed for the mock server or how can I force it to use an incremental behavior for the ids.
The problem of the default behavior of UI5 that generates 9, 416, 6671, 2631, ...
as the ids, is when one of the sets already have an item with id 9
! Then by creating a new item I will have two items in my list with same ids (i.e. 9)!
Looking at the source code of the UI5 mock server, there doesn't seem to be a public setter for the random seed.
If you want to simulate the generation of sequential IDs, you can use MockServer#attachAfter() to change the generated value after the mock server has finished processing the request, like so:
oMockServer.attachAfter("POST", oEvent => {
oEvent.getParameter("oEntity").Id = generateId()
}, "<your entity set name>")
If you need full control of how the mock server responds to a request, you can also override its behavior per request.