2

How is it possible to use a mock server for JSON REST API and not for a oData service? I would like to mock http://localhost:8080/api/v1/configs to get a JSON list of all configurations even if I have no backend connection and I am running the app in mock mode.

The following is not working, it returns furthermore the real data and not the mocked data.

mockserver.js:

sap.ui.define([
  "sap/ui/core/util/MockServer",
  "sap/base/util/UriParameters"
], function (MockServer, UriParameters) {
  "use strict";

  var oTokenRequest = {
    method: "GET",
    path: new RegExp("/actuator/info"),
    response: function (oXhr, sNodeId) {
      jQuery.sap.log.debug("Incoming request for X-CSRF Token");
      oXhr.respondJSON(200, {
        "X-Csrf-Token": "myFakeToken"
      }, {});
    }
  };

  var oMockServer;

  return {

    init: function () {

      var oUriParameters = new UriParameters(window.location.href);

      // configure mock server with a delay
      MockServer.config({
        autoRespond: true,
        autoRespondAfter: oUriParameters.get("serverDelay") || 500
      });

      var oAllConfigurations = {
        method: "GET",
        path: "/configs",  // or "new RegExp(".*?")" for everything after v1/?
        response: function (oXhr, sUrlParams) {
          oXhr.respondJSON(200, {}, JSON.stringify({
            "uuid": "50df30x9-762b-341c-9881-7315l242b6c5",
            "name": "Config1",
            "description": "Mapping for component1",
            "fileVersion": 3,
            "createdAt": 1581517043000,
            "updatedAt": 1589039157000
          }, {
            "uuid": "4f68da04-28a2-4a4e-947k-6d7be70cr03k",
            "name": "MOCKSERVER-Config2",
            "description": "Mapping for component2",
            "fileVersion": 12,
            "createdAt": 1553685823000,
            "updatedAt": 1589363607000
          }, {
            "uuid": "6g6chg1-23a2-4a3o-332a-2a6be08ca02f",
            "name": "Config3",
            "description": "Mapping for component3",
            "fileVersion": 1,
            "createdAt": 1596119686000,
            "updatedAt": 1596119686000
          }));
        }
      };

      var aRequests = [oTokenRequest];
      aRequests = aRequests.concat(oAllConfigurations);

      // create
      this.oMockServer = new MockServer({
        rootUri: "http://localhost:8080/api/v1",
        requests: [oAllConfigurations]
      });


      // start
      this.oMockServer.start();
    }
  };

});

data-sap-ui-oninit in mockServer.html leads to initMockServer.js

initMockServer.js:

sap.ui.define([
    "../localService/mockserver"
], function (mockserver) {
    "use strict";

    // initialize the mock server
    mockserver.init();

    // initialize the embedded component on the HTML page
    sap.ui.require(["sap/ui/core/ComponentSupport"]);
});

Main.controller.js:

//...

 _getConfigList: function () {
      var oModelConfigList = new JSONModel();
      this.request = new BaseRequests();
        return fetch("http://localhost:8080/api/v1/configs")
          .then((response) => {
            if (response.ok) {
              return response.json();
            } else {
              MessageToast.show(response.statusText);
              return null;
            }
          }).then(json => {
          if (json) {
            oModelConfigList.setData(json);
            this.getView().setModel(oModelConfigList, "ConfigList");
          }
        });
      },

//...
Nico S.
  • 116
  • 6
  • your question is unclear if there is no destination used?" Destinations have nothing to do with mocking, if you create the mockserver in JS. "mock server for REST and not for oData" oData is a REST API. Do you mean using something else then the UI5 model implementation? If, yes how would you read this data? – Benedikt Kromer Jul 05 '21 at 12:38
  • @BenediktKromer Sorry, what I wanted to say is, I have no oData service but a JSON API backend. And this means I have no metadata.xml as described in the [Step 27: Mock Server Configuration](https://sapui5.hana.ondemand.com/#/topic/bae9d90d2e9c4206889368f04edab508). So I am struggling to get this running without *oMockServer.simulate*. – Nico S. Jul 05 '21 at 13:23
  • oMockServer.simulate. is only for the ui5 model implementation you have to make your own - but that fairly simple. How do you call this? you can use https://caniuse.com/fetch or https://api.jquery.com/jquery.ajax/ – Benedikt Kromer Jul 05 '21 at 13:37
  • @BenediktKromer: I call this with the Fetch API. I edited my post and added a snipped from the *Main.controller.js*. – Nico S. Jul 05 '21 at 13:52

1 Answers1

1

The UI5-Mockserver is only for the UI5 V2-Model implementation. Hence you need to build your own.

To keep it as simple as possible; i would suggest to pack everything in a delegate and use a global flag to toggle mock/real requests during runtime.

//
// your delegate
//
sap.ui.define([
    "sap/ui/base/Object"
], function (BaseObject) {
    "use strict";

    const mockData = {
        "uuid": "50df30x9-762b-341c-9881-7315l242b6c5",
        "name": "Config1",
        "description": "Mapping for component1",
        "fileVersion": 3,
        "createdAt": 1581517043000,
        "updatedAt": 1589039157000
      }, {
        "uuid": "4f68da04-28a2-4a4e-947k-6d7be70cr03k",
        "name": "MOCKSERVER-Config2",
        "description": "Mapping for component2",
        "fileVersion": 12,
        "createdAt": 1553685823000,
        "updatedAt": 1589363607000
      }, {
        "uuid": "6g6chg1-23a2-4a3o-332a-2a6be08ca02f",
        "name": "Config3",
        "description": "Mapping for component3",
        "fileVersion": 1,
        "createdAt": 1596119686000,
        "updatedAt": 1596119686000
      }

    return BaseObject.extend("my.namespace.delegate.config", {

        read: function(){
           if(!window.MY_NAME_SPACE_MOCK){
            return fetch("api/v1/configs")
            .then((response) => {
              if (response.ok) {
                return response.json();
              } else {
                //MessageToast.show(response.statusText);
                return null;
              }
            })
           }else{
            return new Promise((resolve, reject) => {
                let wait = setTimeout(() => {
                  clearTimout(wait);
                  resolve(mockData);
                }, 2000)
              })
           }
        },

        
    });
});

// usage
sap.ui.define([
    "my/namespace/delegate/config"
], function (Config) {
    onInit: function() {
            this._config = new Config();
            this._config.read()
            .then((data)=>{
              console.log("data can be mock or real depending on MY_NAME_SPACE_MOCK")})
    },
})

//
// switch on/off mocking anywhere 
//
window.MY_NAME_SPACE_MOCK = true;
delete window.MY_NAME_SPACE_MOCK

FYI: domain("localhost") is not part of a normal AJAX request. Once it is deployed; this will not work anymore

Benedikt Kromer
  • 711
  • 6
  • 22
  • Is there a way similar to [Mock non-OData RESTfull services using SAPUI5 MockServer](https://blogs.sap.com/2016/05/30/mock-non-odata-restfull-services-using-sapui5-mockserver/). Because I would like to mock more than one request, this one was only an example. And I also want to use the mocked request later only while executing the OPA5 integration tests in a pipeline and not for executing the app in normal mode. – Nico S. Jul 07 '21 at 09:48
  • Mocking only during OPA: yes that why i think a global flag is the best solution. You can switch it on at the same place, where you would enable mocking. If you work with UI5Tooling & VSCode you could also use something like https://www.npmjs.com/package/mockserver. But if you have only 3-4 API calls thats maybe to much overload. The big thing about the mockserver is to create data on the fly, but there is no metadata document for your JSON-API... therefore this will not work. Your linked example dose the same more or less but has more flexibility/complexity by using regex and requests – Benedikt Kromer Jul 07 '21 at 10:20