如何使用Jasmine模拟服务来忽略任何调用

时间:2016-02-05 03:16:42

标签: angularjs unit-testing karma-runner karma-jasmine

我正在为下面的控制器编写单元测试。我有两个函数loadCountries和loadTimezones我想在页面加载时调用。我想测试国家是否在页面加载时加载。在那个特定的测试中,我不关心时区是否被加载。所以我嘲笑了Timezones服务。但看起来我已经为时区mock返回了一个值。我不想明确地处理它。我期待当我创建SpyObj时,任何未在spy / mock上显式处理的函数调用都将被删除或无效。如果我不链接returnValue,mock就是调用实际函数。我该如何解决这个问题?

'use strict';

angular.module('nileLeApp')
.controller('RegisterController', function ($scope, $translate, $timeout, vcRecaptchaService, Auth, Country, Timezone, RecaptchaService) {
    $scope.success = null;
    $scope.error = null;
    $scope.doNotMatch = null;
    $scope.errorUserExists = null;
    $scope.registerAccount = {};
    $timeout(function () {
        angular.element('[ng-model="registerAccount.email"]').focus();
    });

    $scope.loadCountries = function () {
        Country.getCountries()
            .then(function (result) {
                $scope.countries = result.data;
            });
    };

    $scope.loadTimezones = function () {
        Timezone.getTimezones()
            .then(function (result) {
                $scope.timezones = result.data;
            });
    };

    $scope.loadCountries();
    $scope.loadTimezones();
});

以下是我尝试的测试。

'use strict';

describe('Register Controllers Tests', function () {

describe('RegisterController', function () {

    // actual implementations
    var $scope;
    var $q;
    // mocks
    var MockTimeout;
    var MockTranslate;
    var MockAuth;
    var MockCountry;
    var MockTimezone;
    // local utility function
    var createController;

    beforeEach(inject(function ($injector) {
        $q = $injector.get('$q');
        $scope = $injector.get('$rootScope').$new();
        MockTimeout = jasmine.createSpy('MockTimeout');
        MockAuth = jasmine.createSpyObj('MockAuth', ['createAccount']);
        MockCountry = jasmine.createSpyObj('MockCountry', ['getCountries']);
        MockTimezone = jasmine.createSpyObj('MockTimezone', ['getTimezones']);
        MockTranslate = jasmine.createSpyObj('MockTranslate', ['use']);


        var locals = {
            '$scope': $scope,
            '$translate': MockTranslate,
            '$timeout': MockTimeout,
            'Auth': MockAuth,
            'Country': MockCountry,
            'Timezone': MockTimezone
        };
        createController = function () {
            $injector.get('$controller')('RegisterController', locals);
        };
    }));

    it('should load countries on page load', function () {

        var mockCountryResponse = {data: [{
            'countryId': 1,
            'alpha2Code': "AF",
            'countryName': "Afghanistan"
        }]};

        MockCountry.getCountries.and.returnValue($q.resolve(mockCountryResponse.data));
        // Want to avoid explicitly specifying below line            
        MockTimezone.getTimezones.and.returnValue($q.resolve({}));

        // given
        createController();

        $scope.$apply($scope.loadCountries);
        expect($scope.countries).toEqual(mockCountryResponse);
    });

});

1 个答案:

答案 0 :(得分:0)

这里不可能摆脱and.returnValue,因为控制器链接一个promise并期望Timezone.getTimezones stub返回的对象上的方法(并且它不返回)。

jasmine.createSpyObj仅处理对Timezone方法的调用,而不处理其返回值,这就是and.returnValue存在的原因。

完全没问题

MockTimezone.getTimezones.and.returnValue($q.resolve({}));

基于承诺的规范。