How to switch between httpBackendMocks in protractor test

前端 未结 1 1185
我在风中等你
我在风中等你 2021-01-13 16:24

I am trying to mock responses to API calls within Protractor tests. In different tests (and within tests), the application will POST to an API (always the same URL) with dif

相关标签:
1条回答
  • 2021-01-13 17:06

    A mock-module in protractor is basically code that gets executed into the browser upon each full-page-refresh. It's a mechanism to save you the hassle of doing that yourself, since such a refresh cleans the state of the browser completely (with the exception of cookies of course). As you already found out, until you trigger such a refresh (with browser.get()), your modules are never executed. You can do that manually with browser.executeScript() if you want.

    Regarding the mess that ensues from mocking your back-end - I took the following approach: Have a default mock implementation for your back-end while making it easily overridable and registering it before each test with an init function:

    mocked-backend-base.js

    exports.httpBackendMockBase = function () {
        var exposeBackendCalls = function ($httpBackend) {
            this.getLoginAuthenticated = $httpBackend.whenGET(/login\/authenticated.*/);
            this.getFindStuff = $httpBackend.whenGET(/lookup\/findStuff.*/);
            this.getFullProfile = $httpBackend.whenGET(/api\/full.*/);
        };
    
        angular.module('httpBackendMockBase', ['myClientApp', 'ngMockE2E'])
        .service('httpBackendMockBase', exposeBackendCalls)
        .run(function (httpBackendMockBase, testFixture) {
            httpBackendMockBase.getLoginAuthenticated.respond(function () {
                return [200, null, {}];
            });
            httpBackendMockBase.getFindStuff.respond(function () {
                return [200, { stuff: testFixture.stuff }, {}];
            });
            httpBackendMockBase.getFullProfile.respond(function () {
                return [200, { profile: testFixture.fullProfile }, {}];
            });
        });
    };
    

    If you need parts of it overridden at some point register a new mock module. Remove it in your afterEach block:

    mocked-backend-special-user.js

    exports.httpBackendMock = function() {
        angular.module('httpBackendMockSpecialUser', []).run(function (httpBackendMockBase, testFixture) {
            httpBackendMockBase.getLoginAuthenticated.respond(function() {
                return [200, testFixture.specialUser, {}];
            });
        });
    };
    

    The testFixture is from another module that holds our data and is registered before the mocked-backend-base:

    fixture.js

    exports.data = {
        stuff: null,
        fullProfile: {},
        specialUser: {}
    };
    
    exports.module = function (data) {
        angular.module('backendFixture', []).constant('testFixture', data);
    };
    

    The init function:

    var fixtureModule = require('fixture');
    var baseMockedBackend = require('mocked-backend-base');
    
    browser.addMockModule('backendFixture', fixtureModule.module, fixtureModule.data);
    browser.addMockModule('httpBackendMockBase', baseMockedBackend.httpBackendMockBase);
    
    0 讨论(0)
提交回复
热议问题