lundi 30 novembre 2015

AngularJS - Mocking service functions. Undefined from Jasmine test

I'm having problems. I am using AngularJS v1.4.8 with Angular-Mocks and lodash. I have created a bare-bones simple AngularJS app that simply takes an object and adds onto it.

I would like to know how to mock an AngularJS service and its (instantiated) functions.

Here is my app/main/main.js controller:

'use strict';

angular.module('main', [
    'testapp.models.main'
])
    .config(function ($stateProvider) {
        $stateProvider
            .state('testapp.main', {
                url: '/',
                views: {
                    'mainview@': {
                        controller: 'MainCtrl as mainCtrl',
                        templateUrl: 'app/main/main.template.html'
                    }
                }
            });
    })
    .controller('MainCtrl', function MainCtrl($scope, MainModel){
        this.addItem = MainModel.addItem;
        this.listItems = MainModel.listItems();
    });

and here is its model of app/models/main-model.js:

angular.module('testapp.models.main', [])
    .service('MainModel', function () {

        var items  = [
            { 'id': 0, 'label': 'Item No. 1'},
            { 'id': 1, 'label': 'Item No. 2'},
            { 'id': 2, 'label': 'Item No. 3'},
            { 'id': 3, 'label': 'Item No. 4'}
        ];

        this.listItems = function() {
            return items;
        };

        this.addItem = function(label) {
            var newID = (Object.keys(items).length);
            var theLabel = label ? label :  _.random(10000, 1000000);
            items[newID] = {'id': newID, 'label': 'Item No. ' + theLabel };
        }

    });

and here is my karma.conf.js:

module.exports = function(config) {
    config.set({
        basePath: '../',
        frameworks: ['jasmine'],
        files: [
            // Vendor Files
            'bower_components/angular/angular.js',
            'bower_components/angular-mocks/angular-mocks.js',
            'bower_components/angular-ui-router/release/angular-ui-router.js',
            'bower_components/lodash/lodash.min.js',
            'bower_components/sinon-1.17.2/index.js',

            // App-Specific Files
            'app/index.js',
            'app/models/*.js',
            'app/main/*.js',

            // Test-Specific Files
            'tests/mock/**/*.js'
        ],
        exclude: [],
        reporters: ['progress'],
        port: 9876,
        colors: true,
        logLevel: config.LOG_INFO,
        autoWatch: false,
        browsers: ['PhantomJS'],
        singleRun: true,
        concurrency: Infinity
    })
};

and last not but not least, my mock file tests/mock/controllers/MainMock.js: (where I'm having the problem)

describe('Main Mock Unit Tests', function() {
    'use strict';

    beforeEach(module('ui.router'));
    beforeEach(module('main'));

    var MainCtrl,
        scope;

    var mocklistResource;

    beforeEach(function() {
        mocklistResource = sinon.stub({listItems: function() {}});

        module(function($provide) {
            $provide.value('main', mocklistResource);
        })
    });

    beforeEach(inject(function ($rootScope, $controller, $state) {
        scope = $rootScope.$new();

        MainCtrl = $controller('MainCtrl', {
            $scope: scope,
            $state: $state
        });
        scope.$digest();

    }));

    it('Items object to be 4 (default length)', function () {
        expect(Object.keys(MainCtrl.listItems).length).toBe(4);
    }); // passes


    it('should equal the mock list item object', inject(function() {
        expect(mocklistResource.listItems[0]).toEqual('Item No. 1');
    }))
});

The error comes from the MainMock.js file on the second (and last) it function, gives me:

Expected undefined to equal 'Item No. 1'.

I am trying to get the mocked function of getting the list objects and should return as Item No. 1 successfully but I am getting undefined.

What am I doing wrong? How do I mock this service test? (If there's a better way to do mock tests without sinon, then please let me know.)

Aucun commentaire:

Enregistrer un commentaire