Angular Resource Mocking using TypeScript


This is part of a blog series – please read the intro part and install the prerequisites if you want to follow along.

Sometimes you want to start with your angular app before the backend API is written, or maybe you want to test the app and de-couple it from the real backend API.

With angular you can do this by creating a mock resource intercepts all the calls to the real back-end and returns "fake" data.

Prepare to use mocking features

To use mocking we need to prepare our app similarly to what we did for routing

  1. Add the angular-mocks library (using bower.json or the bower package manager)
  2. Add the lib/angular-mocks/angular-mocks.js script to index.html
  3. Add the angular-mocks typescript definition with tsd install angular-mocks --save in the package manager console

Create the Store Resource Mock

Create a new StoreResourceMock.ts file under app/common/services and add the following content

module app.common.services {
    var mockResource = angular.module("storeResourceMock", ["ngMockE2E"]);

    mockResource.run(mockRun);

    mockRun.$inject = ["$httpBackend"];
    function mockRun($httpBackend: ng.IHttpBackendService): void {
        var stores: app.domain.IStore[] = [];
        var store: app.domain.IStore;

        //prepare store data
        store = new app.domain.Store(1, "Bozo store", "1A", "10AM - 9PM", "10AM - 6PM", "Some store description", "http://www.store.com", "email@store.com");
        stores.push(store);
        store = new app.domain.Store(2, "Delta store", "1A", "10AM - 9PM", "10AM - 6PM", "Some store description", "http://www.store.com", "email@store.com");
        stores.push(store);
        store = new app.domain.Store(3, "Alpha store", "1A", "10AM - 9PM", "10AM - 6PM", "Some store description", "http://www.store.com", "email@store.com");
        stores.push(store);
        store = new app.domain.Store(4, "Beta store", "1A", "10AM - 9PM", "10AM - 6PM", "Some store description", "http://www.store.com", "email@store.com");
        stores.push(store);
        store = new app.domain.Store(5, "Gamma store", "1A", "10AM - 9PM", "10AM - 6PM", "Some store description", "http://www.store.com", "email@store.com");
        stores.push(store);

        //get all stores
        var storeUrl = "/api/stores";
        $httpBackend.whenGET(storeUrl).respond(stores);

        //get single store
        var singleStoreUrl = new RegExp(storeUrl + "/[0-9][0-9]*", '');
        $httpBackend.whenGET(singleStoreUrl).respond(function (method, url, data) {
            var store = { "StoreId": 0 };
            var parameters = url.split('/');
            var length = parameters.length;
            var id = +parameters[length - 1];

            if (id > 0) {
                for (var i = 0; i < stores.length; i++) {
                    if (stores[i].StoreId == id) {
                        store = stores[i];
                        break;
                    }
                }
            }
            return [200, store, {}];
        });

        //catch all for testing purposes,
        //if anything fails we can set a bp here
        $httpBackend.whenGET(/api/).respond(function (method, url, data) {
            return [200, stores, {}];
        });

        //pass through any req for application files
        //so it wont catch requests for html fragments
        $httpBackend.whenGET(/templates/).passThrough();
    }
}

If we dissect the code we have a few different parts

  1. We create a new module “storeResourceMock” and inject [“ngMockE2E”] (angular mocking end to end).The reason we create a new module here is to use a neat trick… that way the only thing we need to do to use this mock in mallApp is to dependency inject it to the mallApp module.
    If we don’t inject it we’ll use the real API.
  2. In the mockRun method we start out by preparing some fake data and store it in the stores[] array
  3. Also in the mockRun function we do routing very similarly to the routing we saw in the routing blogpost but in this case using $httpBackend.whenGET.
    1. when someone requests /api/stores -> respond with stores
    2. when someone requests /api/stores/[0-9][0-9]*  i.e. /api/stores/ followed by a number with one or more digits, grab the corresponding store and return it
    3. when someone requests anything else in /api/  just respond with stores again (default)
    4. when someone requests anything in /templates/ let the request pass through

Save the file and include the script in index.html

<script src="app/common/services/StoreResourceMock.js"></script>

Inject the module to use it

In order to have our calls to /api/stores/… routed to this, the only thing we need to do is inject this module into mallApp in app.ts

var main = angular.module("mallApp", ["ngRoute", "common.services", "storeResourceMock"]);

If you browse the site now you will notice that it is using the fake data instead… and that is all there is to mocking... pretty sweet huh?

Comments (0)

Skip to main content