Here is my current solution.
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
andbreezeMetadata.json
.Abstract the creation of the Breeze Entity Manager to an Angular service
entityManager
.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.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.