Skip to Content
Author's profile photo Klaus Haeuptle

How to replace an ODataModel by a JSON Model

For local testing and unit testing, you can replace an ODataModel by a JSON model. The semantics of these two models is quite different. For testing, the following differences are relevant.

First, you have to replace the ODataModel by a JSONModel.  The function createAlertListWith2Alerts creates a JSON Model with 2 Alerts.

    this.createAlertListWith2Alerts = function() {

      var aAlerts = {

        “AlertQueries(name’Alerts’)” :

  { Alerts :

                [{      RawKey : “A1”,

                         AlertID : “1”,

                         InvestigationObjectType : “CLAIM_RS”, …

  };

       return new JSONModel(aAlerts);

   };

After the JSONModel has been created, the model can be injected with setModel().

Second, the ODataModel knows keys that the JSON Model does not know. The JSON model is purely string based. E.g. with the following statement a list of alerts shall be bound to items of a list.


    alertList.bindAggregation( “items”, {

      path : “/AlertQueries(name’Alerts’)/Alerts” ,

The name ‘Alerts’ is interpreted by the ODataModel as key for calling a specific query in the backend. Since JSON does not know keys, the JSON data format is as follows: In the JSON data, the name’Alerts’ is part of the attribute name. For the binding to JSON model the path AlertQueries(name’Alerts’) is just a string.

      var aAlerts = {

        “AlertQueries(name’Alerts’)” :

  { Alerts :

                [{ RawKey : “A1”,

                    AlertID : “1”,

                   InvestigationObjectType : “CLAIM_RS”, …

Third, the OData expand parameter is ignored by JSON. But this does not matter. You just have to provide the required parameters in the JSON data.

Fourth, an ODataModel has also a function for reading, synchronizing from the backend and for performing changes on the backend. The JSON model does not have these functions. If the productive code uses these functions (e.g. read), you have to implement the used functions in the JSON model test double. In most cases it is sufficient to implement these functions as empty functions.


This blog post is part of a series, like the following blog post to stay tuned and get updates about more topics around software engineering with SAPUI5 and JavaScript:

http://scn.sap.com/community/developer-center/front-end/blog/2013/12/12/engineering-in-javascript

Assigned Tags

      9 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo John Patterson
      John Patterson

      Hi Klaus

      For local testing and unit testing, it is essential to replace an ODataModel by a JSON model

      Wouldnt the recommended approach be sap.ui.core.util.MockServer its an excellent utility for testing UI5 ODataModel's, you can load local JSON files or have it mock the data for you from the metadata.

      Or you could create a fake service and use sinonjs like the ODataModel test does.

      https://openui5.hana.ondemand.com/test-resources/sap/ui/core/qunit/ODataModel.qunit.html

      And if you got node.js running locally you could easily use jaydata's odata-server for mocking gateway services.

      Cheers

      JSP

      Author's profile photo Klaus Haeuptle
      Klaus Haeuptle
      Blog Post Author

      Thank you very much for the feedback. The sentence is not precise enough, there are further approaches. I have adjusted the blog.


      1)     Wouldnt the recommended approach be sap.ui.core.util.MockServer its an excellent utility for testing UI5 ODataModel's, you can load local JSON files or have it mock the data for you from the metadata.

      2) Or you could create a fake service and use sinonjs like the ODataModel test does. https://openui5.hana.ondemand.com/test-resources/sap/ui/core/qunit/ODataModel.qunit.html

      3)     And if you got node.js running locally you could easily use jaydata server for mocking gateway services.


      1)     As we started developing our application the MockServer was still experimental. I will try the MockServer for the development of the our application. Benefits could be that you do not have to implement the test double on your own. Still the mentioned approach worked quite well for our application and allows implementing a domain model with readable test data.

      2)     For testing the ODataModel this approach works quite well, but I would not use it for testing an application, since it requires more knowledge about implementation details. (how the ODataModel uses XHR Requests)

      3) Unit Tests should be self-contained and do not have fragile dependencies. If you use it, you have to ensure that the configuration works on each developer machine and in the continuous integration landscape. I have not tried it yet and it depends on the system landscape, could this be fragile from your perspective?


      Do you see further benefits of these approaches?


      Thanks

      Klaus

      Author's profile photo John Patterson
      John Patterson

      Hi Klaus

      A lot of the testing i do with the ODataModel is around the expected results of an OData service call and the affects this has on the binding contexts and objects that rely on them.

      The issues I have with swapping a JSONModel for an ODataModel

      - the context paths work differently, i have seen and used the utility for making the paths interchangable and it works ok for simple scenarios, ODataModel bindings are a lot different from the ones in the JSONModel and you do need to fake service calls.

      - most of the functionality is missing in the JSONModel, looking at the public interfaces, you will see there are approx 5 X more methods for the ODataModel, the JSONModel doesnt have CRUD functions and that is a big hole to fill.

      I kind of agree with you on point 3 and introducing fragile dependencies, I am waiting for some sort of standard like Karma to be released for UI5 development, sharing the configuration and integrating the CI and other tools would be very easy.

      Cheers

      JSP

      Author's profile photo Klaus Haeuptle
      Klaus Haeuptle
      Blog Post Author

      Hi John,


      could you post or send me the code I am interested in examples where the approach is too complicated or does not work at all. For our scenario it was ok to double the service functions (e.g. create or for batch operations), which were not supported by the JSON model. Still for the next project I will try MockServer.

      We are working on a blog post how to use Karma for SAPUI5, but this will take some time. Do you see benefits of using jaydata server compared to MockServer or the JSONModel?


      Thanks,

      Klaus

      Author's profile photo John Patterson
      John Patterson

      Hi Klaus

      wrt code i will dig up a couple of examples sanitise and share, better yet i will write a blog about using the MockServer with OData.

      That is great news about the blog on Karma, I have to admit i tried get it working and had issues with dependencies and fixtures, I have my gruntjs config setup with similar features, it watches for changes and gives "instant karma" like feedback, definitely liking TDD alot more now.

      Do i see any benefits of using a local OData server, being able to rapidly immitate Netweaver Gateway services before you write them is a huge win, i can produce prototypes and poc's a lot quicker, also means the frontend and backend concerns can be worked on in isolation, also means a lot of the UI5 work can be done offline, perfect for a long commute with limited or no network access, again only suitable for simple scenarios and use cases.

      Now I have started to use the sap.ui.core.util.MockServer I think the two currently compliment each other nicely. I can create metadata and <entity>.json files and services very quickly using JavaScript in jayserver and have the files created loaded into the ui5 mockserver at runtime.

      Once the _generateMockdata function in sap.ui.core.util.MockServer which creates mock data based on the services metadata is set up to use templates like mockJSON things may change.

      Interesting discussion - thanks

      JSP

      Author's profile photo Klaus Haeuptle
      Klaus Haeuptle
      Blog Post Author

      Hi John,

      I am looking forward to your blog.

      So the additional benefit of jayserver compared to MockServer is the generation of random test data?  And this could also be supported by MockServer, then you would not need jayserver anymore for doubling OData?

      Thanks,

      Klaus

      Author's profile photo John Patterson
      John Patterson

      Hi Klaus,

      Sorry long week, test data needs to be predictable and not random. Forget that last paragraph, still templates would be a nice feature.

      I had to check JS Bin - OData MockServer , the generated date changes. You can see why i thought it was static.

      Cheers

      JSP

      Author's profile photo Hendrik Lock
      Hendrik Lock

      I am not sure that I totally understand the problem, but intuitively I would separate two concerns: testing the working of the OData service as expected, and testing the unit consuming the OData response. The second case could probably use a specific test isolation avoiding the mentioned JSON issues.

      Author's profile photo Rodrigo Jordao
      Rodrigo Jordao

      Hello,

      I think we're missing a couple of higher-level abstractions for models in SAPUI5. I'd like to see abstract descriptions of things like ReadOnlyModel, WriteableModel, NavigableModel, etc... that the ODataModel would "adhere" to and that would make the creation of stub or mock models easier. I think having to adhere a JSONModel to an ODataModel is not the right way to think about the application. It's like mocking concrete classes in a language like Java. The fact that Javascript doesn't have interfaces is no excuse to not think about the abstract description of behavior that the application should work against.

      As a separate note, I've also used sinon.js (through the MockServer) to create an in-memory store that I could maintain in Javascript and serve read, write and navigation requests to stub the backend OData server. That gave us a lot of freedom and speed in writing tests and in developing the application in general.

      Regards,

      Rodrigo Jordao