Reason
To make use of ngMockE2E
, or more specifically $httpBackend, in integration tests sporting Protractor, Selenium and Jasmine, the documentation suggests including a reference to angular-mocks.js
in a script-tag.
Doing so clutters production code with references to test frameworks, which is a big no-no in my book. Hence we’ll load the angular-mocks.js
API as a mock module instead using Protractor’s own API.
Pros:
- No need to modify production code.
- Load angular mocks only for specific specs/scenarios easily.
Cons:
- None that I know of.
Code
The following snippet just reads the contents of the angular-mocks.js
file and exposes it via the mock
field of the exported object. Placing this in a separate file makes it easy to reuse across specs.
// File: "angularMocks.module.js" module.exports = { mock: getScript() }; function getScript() { var path = require("path"), fs = require("fs"), angularMocksDir = path.dirname(require.resolve("angular-mocks")), angularMocksFilePath = path.join(angularMocksDir, "angular-mocks.js"), script = fs.readFileSync(angularMocksFilePath).toString(); return script; }
Example
Now that the mock script is easily available it can be sent to the “browser under test” using browser.addMockModule(“<module name>”, <payload>) in a beforeEach
. If you’re certain that you need the $httpBackend mock in all your specs you could opt to load it in a beforeAll function instead, and move the browser.clearMockModules()
to a afterAll function.
To make the application we’re testing load ngMockE2E
we need an intermediary module which depends on both our “main app module” and ngMockE2E
as per the installation instructions.
// File: "WeekSchedule.controller.spec.js" describe("Controller: WeekSchedule", function () { beforeEach(function () { // Load angular-mocks.js into the browser. var angularMocksScript = require("./path/to/file/angularMocks.module.js").mock; browser.addMockModule("ngMockE2E", angularMocksScript); // Load our "trigger module", which depends on both our app and ngMockE2E, into the browser. browser.addMockModule("SomeNameThatsNotInUse", mockModuleLoader); }); afterEach(function(){ // Remove the mock modules again as this isn't done automatically. browser.clearMockModules(); }); function mockModuleLoader() { angular.module("SomeNameThatsNotInUse", ["WorkSchedule", "ngMockE2E"]) .run(function ($httpBackend) { // Define mock logic here: // E.g. ".../WeekSchedule/2015-W35" $httpBackend.whenGET(/\/api\/v1\/WeekSchedule\/\d{4}-W\d{2}/).respond(200, [{message:"Hello World!"}]); // Pass through all other requests, throw an error or whatever fits the spec. $httpBackend.whenGET(/.*/).passThrough(); }); } it("should fetch data from the backend", function () { // [...] }); })