Angular Karma / Jasmine单元测试不起作用

时间:2016-02-05 00:28:47

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

我试图为我的新Angular App编写单元测试并遇到麻烦。下面是我的控制器。

<style>
    .fulldiv {
        width: 100%;
    }
    .left {
        float: left;
    }
    .right {
        float: right;
    }
    .float-none {
        float:none;
    }
    .float-inherit {
        float: inherit;
    }


</style>

<div class="fulldiv">
    <img src="~/images/winter1.png" class="img-responsive left" style="width:65%;"/>
    <img src="~/images/woman2.png" class="img-responsive right" style="width:35%;" />
    <img src="~/images/adult2.png" class="img-responsive left" style="width:35%;" />
    <img src="~/images/portfolio.png" class="img-responsive float-none" style="width:30%;" />
    <img src="~/images/feet2.png" class="img-responsive float-none" style="width:65%;" />
</div>

以下是我尝试的测试。

'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;
            });
    };

    // ============ Recaptcha specific code START ===============
    $scope.recaptcha = {};
    $scope.recaptcha.recaptchaResponse = null;
    $scope.recaptchaWidgetId = null;

    $scope.setResponse = function (response) {
        $scope.recaptcha.recaptchaResponse = response;
        $scope.recaptchaMissing = false;
    };
    $scope.setWidgetId = function (widgetId) {
        $scope.recaptchaWidgetId = widgetId;
    };
    $scope.cbExpiration = function () {
        $scope.recaptcha.recaptchaResponse = null;
    };
    // ============ Recaptcha specific code END ===============

    $scope.createAccount = function () {
        Auth.createAccount($scope.registerAccount).then(function (response) {
            $scope.success = true;
        }).catch(function (response) {
            $scope.success = false;
        });
    }

    $scope.register = function () {

        $scope.recaptchaMissing = false;
        $scope.recaptchaInvalid = false;

        if ($scope.recaptcha.recaptchaResponse != null) {
            RecaptchaService.verify($scope.recaptcha).$promise
                .then(function (response) {
                    if (response.data) {
                        $scope.createAccount();
                    } else {
                        $scope.recaptchaInvalid = true;
                        vcRecaptchaService.reload($scope.recaptchaWidgetId); // Reload captcha
                    }
                }).catch(function (response) {
            });
        } else {
            $scope.recaptchaMissing = true;
        }
    };

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

上述期望不起作用,因为$ scope.countries未定义。以下是错误消息。

'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 = [{
            'countryId': 1,
            'alpha2Code': "AF",
            'countryName': "Afghanistan"
        }];

        MockCountry.getCountries.and.returnValue($q.resolve(mockCountryResponse));
        MockTimezone.getTimezones.and.returnValue($q.resolve());
        MockAuth.createAccount.and.returnValue($q.resolve());

        // given
        createController();

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

});

另外,我看到测试因某些奇怪的原因被调用了两次。下面是我的Karma配置文件。

TypeError: 'undefined' is not an object (evaluating 'result.data')

我在最近几天坚持编写单元测试,因为我觉得它们很混乱而且不像Java那样简单。将不胜感激任何帮助。

1 个答案:

答案 0 :(得分:1)

  

上述期望不起作用,因为$ scope.countries未定义

^^那不是真的。并不是$ scope.countries未定义,result未定义,而且不是result您要分配给$scope.countries,而是$scope.timezonesMockTimezone.getTimezones.and.returnValue($q.resolve()); 相关的resolve() }}

我认为这是你的问题:

$scope.loadTimezones();

您隐式将undefined传递给SELECT Title, FIRSTNAME, SURNAME, COUNT(BORROWINGS.booknumber) FROM Books, Authors, Borrowings WHERE BOOKS.Booknumber = BORROWINGS.Booknumber AND BOOKS.Authornumber = Authors.Authornumber AND DateBorrowed > #1-9-2014#` (D/M/Y) GROUP BY TITLE, FIRSTNAME, SURNAME; 函数,并且在实例化控制器时会抛出错误。 它抛出了这个错误,因为你在控制器的末尾有这一行:

{{1}}

因此我停止了自己初始化控制器。现在我使用从HTML启动的ng-init来完成它。如果你做出与我相同的改变,你将来不会再遇到这样的问题。