Application with fake data source for UI development

≯℡__Kan透↙ 提交于 2019-12-11 03:39:56

问题


I have a web application with an Angular / Breeze client side calling into a Breeze Web API, which uses an Entity Framework code first model. I have a datacontext (Angular service) responsible for all communications with server.

I would like to completely separate the server development from the client side development so developers need not even have .NET installed on their system. I would like the solution to require very little coding in way of creating fakes, because the app is changing frequently and I do not want to have to rewrite fakes every time my implementation changes. I have a bunch of test data in the database that I would like to make available on the client.

What is a good way (standard way?) to achieve this?


回答1:


Just create mocks. You don't even have to make a RESTful call if you don't want to, just have your service decide whether to hit the server or pull from cache and load up your cache locally on start -

function loadMocks (manager) {
    var personMockOne = manager.createEntity('Person', { id: 1, firstName: 'John', lastName: 'Smith' });
    var companyMockOne = manager.createEntity('Company', { id: 1, name: 'Acme Inc.' });
    companyMockOne.employees.push(personMockOne);
}

http://pwkad.wordpress.com/2014/02/02/creating-mocks-with-breeze-js/

To Expand...

Doing this requires a bit of extra set up. I personally always write my queries separate from my controller / view model logic through a service which takes parameters. A few example parameters are always something like parameters and forceRemote. The idea is that when you go to execute the query you can decide whether to hit the server or query locally. A quick example -

function queryHereOrThere (manager, parameters, forceRemote) {
    var query = breeze.EntityQuery().from('EntityName').using(manager);
    query.where(parameters);

    if (!forceRemote) {
        query.executeQueryLocally();
    } else {
        query.executeQuery();
    }
}



回答2:


Here is my current solution.

  1. Get data from the server with a 'unit test' that creates a Breeze Web API controller and uses it to gather the breeze metadata and all the test data from the database, then writes that data to testData.json and breezeMetadata.json.

  2. Abstract the creation of the Breeze Entity Manager to an Angular service entityManager.

  3. Create a fakeEntityManager Angular service, which: 1) creates the entity manager, 2) overrides the EntityManager.executeQuery function to always use the local version, and 3) loads up the mgr with the test data. The code for that service is below.

  4. In the datacontext service, use the $injector service to conditionally inject a real or a fake entity manager.

datacontext.js

angular.module('app').factory('datacontext', ['$injector','config', datacontext]);

function datacontext($injector, config) {

    if (config.useLocalData === true) {
        var mgr = $injector.get('fakeEntityManager');
    } else var mgr = $injector.get('entityManager');

    ...

fakeEntityManager.js

(function() {
    'use strict';

    var serviceId = 'fakeEntityManager';
    angular.module('app').factory(serviceId, ['breeze', 'common', em]);

    function em(breeze, common) {
        var $q = common.$q;
        var mgr = getMgr();
        populateManager(["Projects", "People", "Organizations"]);
        return mgr;            

        function getMgr() {
            breeze.EntityManager.prototype.executeQuery = function(query) {
                return $q.when(this.executeQueryLocally(query)).then(function (results) {
                    var data = {
                        results: results
                    };
                    if (query.inlineCountEnabled == true) data.inlineCount = results.length;
                    return data;
                });
            };
            var metaData = < PASTE JSON HERE > 
            new breeze.ValidationOptions({ validateOnAttach: false }).setAsDefault();
            var metadataStore = new breeze.MetadataStore();
            metadataStore.importMetadata(metaData, true);

            return new breeze.EntityManager({
                dataService: new breeze.DataService(
                    {
                        serviceName: "fakeApi",
                        hasServerMetadata: false // don't ask the server for metadata
                    }),
                metadataStore: metadataStore
            });
        }

        function populateManager(resources) {
            var testData = < PASTE JSON HERE >;
            resources.forEach(function (resource) {
                testData[resource].forEach(function (entity) {
                    mgr.createEntity(mgr.metadataStore.getEntityTypeNameForResourceName(resource), entity);
                });
            });
        }
    }
})();

If you don't use inlineCount queries there is no need to override executeQuery. You can just add the following property to the EntityManager constructor's parameter:

queryOptions: new breeze.QueryOptions({ fetchStrategy: breeze.FetchStrategy.FromLocalCache })

Todo: Override the EntityManager.saveChanges() function (or somehow configure the entity manager) to prevent calls to the server while still allowing entities to be edited and saved locally.



来源:https://stackoverflow.com/questions/23507140/application-with-fake-data-source-for-ui-development

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!