admin管理员组

文章数量:1336632

I'm in the process of upgrading an AngularJS v1.5 project to Angular 4.x. During development of the original AngularJS application, we would use the ngMocks package to simulate actual web service API responses, and display the data accordingly on the page. This was incredibly helpful during development as I didn't have to hard-code values for removal later on. Best of all, we configured Webpack to only include the mock data during development, and ignore those mock data files when building our application for production use. The mock data was configured like this:

/* app-login.mock.js */
import angular from 'angular';
import 'angular-mocks';

angular.module('app').run(function ($httpBackend) {
    $httpBackend
        .whenPOST('./api/auth')
        .respond(function(method, url, data) {
            var credentials = angular.fromJson(data);
            if (credentials.username == 'gooduser') {
                return [200, {'token': createToken(credentials.username)}];
            } else {
                return [401, {'errorMsg': 'Mock login only allows username "gooduser"'}];
            }
        });
});

function createToken(username) {
    // Create a token, which is valid enough for testing purposes.
    // This token is based on the actual token generated by the web service.
    let currentTime = new Date();
    let futureTime = new Date(currentTime.getTime() + ((currentTime.getHours() + 8) * 60 * 60 * 1000));

    let header = {
        alg: 'HS512'
    };

    let payload = {
        exp: futureTime.getTime() / 1000,
        sub: username,
        roles: 'SOME_APPLICATION_ROLES',
        iat: currentTime.getTime() / 1000
    };

    return `${btoa(angular.toJson(header))}.${btoa(angular.toJson(payload))}`;
}

Webpack was then configured to include all "mock" files into the built bundle, which could then be displayed as if it were a real HTTP response.

/* webpack.config.js */
const isProd = process.env.NODE_ENV === 'production';

const entry = {
    app: (() => {
        let app = [
            'babel-polyfill',
            path.join(PATHS.app, 'pollyfills.ts'),
            path.join(PATHS.app, 'main.ts')
        ];

        if (isProd) {
            app.push(path.join(PATHS.app, 'app.prod.js'));
        } else {
            app.push(path.join(PATHS.app, 'app.mock.js'));
        }

        return app;
    })()
};

module.exports = {
    entry,
    // ...other exports
};

And then the app.mock.js file:

/* app.mock.js */
var mockContext = require.context(".", true, /\.mock$/);
mockContext.keys().forEach(mockContext);

I've scoured the internet looking for a solution that works just as well as our old one, though I haven't e up with any good answers. Best I've found are tutorials on how to set up Unit Tests that return mock data, and while that's useful for testing functionality it doesn't help me test the application during the development process.

I also have seen some documentation on setting up Interceptors using the new HttpClient class found within Angular 4, but I'm not sure how to add it to our Webpack configuration under the condition of only being allowed during development. Does anyone have any advice on what to do?

I'm in the process of upgrading an AngularJS v1.5 project to Angular 4.x. During development of the original AngularJS application, we would use the ngMocks package to simulate actual web service API responses, and display the data accordingly on the page. This was incredibly helpful during development as I didn't have to hard-code values for removal later on. Best of all, we configured Webpack to only include the mock data during development, and ignore those mock data files when building our application for production use. The mock data was configured like this:

/* app-login.mock.js */
import angular from 'angular';
import 'angular-mocks';

angular.module('app').run(function ($httpBackend) {
    $httpBackend
        .whenPOST('./api/auth')
        .respond(function(method, url, data) {
            var credentials = angular.fromJson(data);
            if (credentials.username == 'gooduser') {
                return [200, {'token': createToken(credentials.username)}];
            } else {
                return [401, {'errorMsg': 'Mock login only allows username "gooduser"'}];
            }
        });
});

function createToken(username) {
    // Create a token, which is valid enough for testing purposes.
    // This token is based on the actual token generated by the web service.
    let currentTime = new Date();
    let futureTime = new Date(currentTime.getTime() + ((currentTime.getHours() + 8) * 60 * 60 * 1000));

    let header = {
        alg: 'HS512'
    };

    let payload = {
        exp: futureTime.getTime() / 1000,
        sub: username,
        roles: 'SOME_APPLICATION_ROLES',
        iat: currentTime.getTime() / 1000
    };

    return `${btoa(angular.toJson(header))}.${btoa(angular.toJson(payload))}`;
}

Webpack was then configured to include all "mock" files into the built bundle, which could then be displayed as if it were a real HTTP response.

/* webpack.config.js */
const isProd = process.env.NODE_ENV === 'production';

const entry = {
    app: (() => {
        let app = [
            'babel-polyfill',
            path.join(PATHS.app, 'pollyfills.ts'),
            path.join(PATHS.app, 'main.ts')
        ];

        if (isProd) {
            app.push(path.join(PATHS.app, 'app.prod.js'));
        } else {
            app.push(path.join(PATHS.app, 'app.mock.js'));
        }

        return app;
    })()
};

module.exports = {
    entry,
    // ...other exports
};

And then the app.mock.js file:

/* app.mock.js */
var mockContext = require.context(".", true, /\.mock$/);
mockContext.keys().forEach(mockContext);

I've scoured the internet looking for a solution that works just as well as our old one, though I haven't e up with any good answers. Best I've found are tutorials on how to set up Unit Tests that return mock data, and while that's useful for testing functionality it doesn't help me test the application during the development process.

I also have seen some documentation on setting up Interceptors using the new HttpClient class found within Angular 4, but I'm not sure how to add it to our Webpack configuration under the condition of only being allowed during development. Does anyone have any advice on what to do?

Share Improve this question edited Sep 29, 2017 at 19:04 georgeawg 49k13 gold badges77 silver badges98 bronze badges asked Sep 29, 2017 at 18:23 Z. Charles DziuraZ. Charles Dziura 9334 gold badges18 silver badges41 bronze badges 2
  • Have you tried json-server . I use that in our app – Vamshi Commented Sep 30, 2017 at 3:35
  • I've never heard of it, but I'll have myself a look. Thanks for the suggestion! – Z. Charles Dziura Commented Sep 30, 2017 at 16:10
Add a ment  | 

1 Answer 1

Reset to default 6

I use the angular-in-memory-web-api. You can find it here: https://github./angular/in-memory-web-api

UPDATE: The repo was moved here, within the angular/angular repo: https://github./angular/angular/tree/e0dfa42d6e656124f3c3d78e178b1bf091b38e79/packages/misc/angular-in-memory-web-api

It intercepts all of your http calls and works with sample data you provide.

To change from dev to production, you need to remove the imports. Or you could possibly write two different modules, one with the dev imports and one with the production imports and include one or the other with webpack similar to what you do now. (But I have not tried this.)

You set up your data like this:

import { InMemoryDbService } from 'angular-in-memory-web-api';

import { IProduct } from './product';

export class ProductData implements InMemoryDbService {

    createDb() {
        let products: IProduct[] = [
            {
                'id': 1,
                'productName': 'Leaf Rake',
                'productCode': 'GDN-0011',
                'releaseDate': 'March 19, 2016',
                'description': 'Leaf rake with 48-inch wooden handle.',
                'price': 19.95,
                'starRating': 3.2,
                'imageUrl': 'http://openclipart/image/300px/svg_to_png/26215/Anonymous_Leaf_Rake.png',
                'tags': ['rake', 'leaf', 'yard', 'home']
            }, 
            // ...
        ];
        return { products };
    }
}

And you build your data access service using the normal Http or HttpClient.

I have a full example with all CRUD operations here: https://github./DeborahK/Angular2-ReactiveForms

本文标签: javascriptAngular 4How to Simulate Mock Data for Prototyping and DevelopmentStack Overflow