Harrington Web

Mock HTTP calls with Angular and Protractor

Friday, February 17, 2017
Mocking Data

One of the benefits using AngularJS is also using some test tools like Protractor. Protractor is a tool that was made for Angular testing. Many times when testing you will need to mock some data so that you can see if your application responds in the correct manner. Let us assume that we have the following HTML file running our application.
<!doctype html>
<html ng-app="demo">
    <head>
        <title>Hello</title>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular-mocks.js"></script>
        <script src="hello.js"></script>
    </head>

    <body>
        <div ng-controller="Hello">
            <p>Hello <span id="gname">{{exampleResponse.name}}</span></p>
        </div>
    </body>
</html>
This web application loads a few javascript files from a CDN (content delivery network) and also a "hello.js". In order to get mocking to work we have to make sure that there is a reference to "angular-mocks.js".
Then under "hello.js" we define a simple HTTP request that will get some data and return it in the $scope.exampleResponse variable. This response is exactly what we want to mock.
angular.module('demo', [])
.controller('Hello', function($scope, $http) {
    $http.get('http://baseUrl/exampleResponse').
        then(function(response) {
            $scope.exampleResponse = response.data;
        });
});
Install some basic packages for protractor.
npm install protractor jasmine-core httpbackend
Setup for protractor-conf.js
exports.config = {

    directConnect: true,
    //seleniumAddress: 'http://localhost:4444/wd/hub',

    suites: { "main" : ["spec/**/*.js"]},

    capabilities: {
        "browserName": "chrome"
    },

    baseUrl: "http://localhost:8000/",

    framework: 'jasmine2',

    jasmineNodeOpts: {
        defaultTimeoutInterval: parseInt(process.env.TIMEOUT) || 30000,
        verbose: true,
        realtimeFailure: true,
        //print: function() {}
    },

    resultJsonOutputFile: 'result.json',

    onPrepare: function() {},

    afterLaunch: function(exitCode) {}
};
The test script, now we can have some fun. The first thing we can do is require httpbackend. There is another way to accomplish mock however httpbackend provides a really simple means of getting the job done. For this example we also create a before and after hook that will allow us to define backend and also clear and teardown the variable.
var HttpBackend = require('httpbackend');
var backend;

describe('A test', function() {
    beforeEach(() => {
        backend = new HttpBackend(browser);
    });

    afterEach(function() {
        backend.clear();
    });

    it('should diplay Ben as the name', function() {
        backend.whenGET(/exampleResponse/).respond({"name": "Ben"});
        browser.get('http://localhost:8000');
        expect($('#gname').getText()).toBe("Ben");
    });
})
If you remember from back in the "hello.js" we did a GET request. "$http.get('http://baseUrl/exampleResponse')" Within the it statement, this is where we can have backend tell Angular that when it needs this GET request send this new data. "backend.whenGET(/exampleResponse/).respond({"name": "Ben"});"
That is all there is too it. For more information and other HTTP handlers like POST, check our the documentation on httpbackend https://www.npmjs.com/package/httpbackend. You can also take a look at an example of this work on my github and play with it yourself. https://github.com/blh0021/protractor-angular-demos

No comments :

Post a Comment