I know of two such mocking frameworks which can help you.
One is ng-apimock and another is json-server.
I have recently started using ng-apimock API for mocking some backend REST calls. It seems good so far as I am able to see some interesting functions available in this npm library. Here, you can define and select Scenarios and Presets(multiple mocks) and basically configure which mock to use for which e2e test case. This basically means a fine-grained control over the e2e tests by providing essential response data as required. It is not eas to set-up as many blogs say on the internet, this I can definitely confirm. But it looks like the solution for my use-case.
I basically had to setup up a proxy.conf.json in addition to defining mocks, and presets(optional), and had to maintain some protractor configuration also for working with this API.
Basically, you can configure exactly what values should be returned from which API endpoint on e2e test run, and along with it, can even disable change what values should be returned for each e2e test case also. There's one option called as passThrough also in this API, which means you can even choose that scenario to make sure the mocks are disabled and calls go to your real HTTP backend.
If you want more details, let me know and I can probably provide you with details on how to configure it.
UPDATE(LONG POST ALERT!!) :
Mock Server Setup(ng-apimock & protractor with express, concurrently)
mock-server.js
const express = require('express');
const apimock = require('@ng-apimock/core');
const devInterface = require('@ng-apimock/dev-interface');
const app = express();
app.set('port', (process.env.PORT || 30020));
apimock.processor.process({
src: 'mockapi', //name of the folder containing mocks and presets
watch: true
});
app.use(apimock.middleware);
app.use('/mocking', express.static(devInterface)); //endpoint for UI Dev Interface
app.listen(app.get('port'), function() {
console.log('mock app-server running on port', app.get('port'));
});
package.json(scripts section)
"test:e2e": "ng e2e",
"start:mockapi": "node mockapi/mock-server.js",
"e2e": "concurrently -k -s first \"npm run start:mockapi\" \"npm run test:e2e\""
package.json(devDependencies section)
"@ng-apimock/core": "^2.6.0",
"@ng-apimock/dev-interface": "^1.1.0",
"@ng-apimock/protractor-plugin": "^1.1.0",
"ng-apimock": "^1.4.9",
"concurrently": "^6.0.1",
"express": "^4.17.1",
mock-proxy.conf.json
A needed proxy configuration file was added inside mocks folder. This is to ensure that the proxy http backend calls go to the correct mock server Url.
Additional endpoint is added for the UI Dev Interface which can be used during development for manual configuration of scenarios and other details related to the defined mocks. After starting mock api server, localhost:30020/mocking can be launched. All to passThrough Option can be selected from UI if we want all mock scenarios to be disabled, and the call will go to the actual REST backend app-server.
{
"/api/*": {
"target": "http://localhost:30020",
"secure": false,
"logLevel": "debug"
},
"/application-server/*": {
"target": "http://localhost:30020",
"secure": false,
"logLevel": "debug"
},
"/ngapimock/*": {
"target": "http://localhost:30020",
"secure": false,
"logLevel": "debug"
},
"/mocking/*": {
"target": "http://localhost:30020",
"secure": false,
"logLevel": "debug"
}
}
((Note: our Dev App Server generally runs on 30020))
Protractor Configuration
ngApiMock related options pertaining to Angular version, protractor plugin package and to use custom global ngApiMock client name(to be the only name declaration for use in e2e specs for API method calls) were added in protractor.conf.js.
options: {
globalName: 'ngApiMockClient', //this name should be used for declaration of Client in e2e tests
}
Below Options were removed:
useAllAngular2AppRoots → removed to avoid conflict with the version specification of Angular which comes with ng-apimock protractor options.
baseUrl → removed to avoid conflicts with the proxy configuration that is described in the next step.
angular.json Changes
Addition of a new Webpack DevServer target serve-e2e for pointing to the mock-proxy.conf.json. This target is then called in place of regular "serve" target for launching the application during a typical E2E tests run. This new target addition ensures that we don't use the proxy configuration for the general application launch triggered on "ng serve" which is used often during development.
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "tnps-portal:build"
},
"configurations": {
"production": {
"browserTarget": "tnps-portal:build:production"
}
}
},
"serve-e2e": {
"builder": "@angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "tnps-portal:build",
"proxyConfig": "mockapi/mock-proxy.conf.json"
},
"configurations": {
"production": {
"browserTarget": "tnps-portal:build:production"
}
}
},
and specifying serve-e2e as e2e devServer target...
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "e2e/protractor.conf.js",
"devServerTarget": "tnps-portal:serve-e2e"
},
"configurations": {
"production": {
"devServerTarget": "tnps-portal:serve:production"
E2E Usage
All the mock files should be declared as *.mock.json and presets as *.preset.json before starting the mock api server, for processing of all mocks and presets. This default configuration can be modified by specifying regex pattern of mocks and presets in the mock-server.js file, e.g. it can be made *Mock.json & *Preset.json
import { Client } from '@ng-apimock/base-client';
declare const ngApiMockClient: Client; // !IMPORTANT: the name of the constant should match the global name defined in protractor.conf.js
it('sample mock test', () => {
ngApiMockClient.selectScenario('sample-mock-name', 'sample-scenario-name',);// sample-mock-name is the name of the mock, and sample-scenario-name is the response scenario name as defined in some sample.mock.json
The above code should choose scenario for a specific mock, which basically means some specific data can be returned for some specific use-cases. This data is also defined in sample.mock.json under responses as follows -
"name": "sample-mock-name",
"isArray": true,
"request": {
"url": "application-server/actual-endpoint-name", // Endpoint Url for the Mock Request
"method": "GET" // HTTP call type - GET, POST, etc.
},
"responses": {
"fileDataScenario": {
"file": "../data/sampleData.json", // returns json Array data from a file
"default": false
},
"emptyListScenario": {
"data": [{}], // returns data as array, "isArray" : true mandatory for the same mock.
"default": true // this scenario's data will be returned if no scenario is selected from E2E Code or /mocking UI.
}
Selecting scenario will suffice for testing simple use-cases. For more complex cases where you need to make sure to return specific scenarios from some specific mocks during runtime, please configure presets as below -
{
"name": "sample-preset",
"mocks": {
"sample-mock-name": {
"scenario": "fileDataScenario",
"delay": 3000
},
"sample-mock-name-2": {
"scenario": "someOtherScenarioFromMock2",
"delay": 3000
},
"sample-mock-name-3": {
"scenario": "oneMoreScenarioFromMock3",
"delay": 3000
}
},
"variables": {
"something": "awesome"
}
}
and in e2e specs
ngApiMockClient.selectPreset('sample-preset');
Above code blocks describe some common examples which might be useful for mocking REST calls for E2E tests with protractor and ng-apimock.
ng-apimock Docs