Jasmine 如何设置间谍的响应

Jasmine how do I set the response of a spy

我的 Angular.js 控制器中有以下内容

function alreadyRegistered() {
    if(reg.regForm.email.$valid){
        console.log('this is logged in my console.');
        authFactory.doesUserExist(reg.user)
            .then(function(response){
                console.log('this line if never hit');
                if(response) {
                    reg.regForm.email.$setValidity('userExists', false);
                } else {
                    reg.regForm.email.$setValidity('userExists', true);
                }
            })
            .catch(function(err){
                reg.error = err;
            });
    } else { 
        reg.regForm.email.$setValidity('userExists', true); // Remove userExists validation error.
    }
};

我想通过将 .then() 内的响应设置为 true 或 false 来测试验证是否正常工作。但是我无法让我的测试进入 .then().

这是我的测试:

describe('Registration Controller Tests', function() {
    var $controller, $scope, defer, doesUserExistSpy, authFactory, Registration,

    beforeEach(module('enigma'));

    beforeEach(inject(function (_$controller_, _$rootScope_, $q, $injector) {
        $controller = _$controller_;
        $scope = _$rootScope_;
        defer = $q.defer();

        // Create spies
        doesUserExistSpy = jasmine.createSpy('doesUserExist').and.returnValue(defer.promise);

        authFactory = {
            register: registerSpy,
            doesUserExist: doesUserExistSpy
        };    

        // Init register controller with mocked services
        Registration = $controller('Registration', {
            $scope: $scope,
            authFactory: authFactory,
            $state: $state
        });

        // digest to update controller with services and scope
        $scope.$digest();
    }));

    describe('check email field validity', function () {
        var element, regForm;

        beforeEach(inject(function ($rootScope, $compile) {
            $scope = $rootScope;
            element = angular.element(
                '<form name="regForm">' + 
                    '<input type="email" ng-model="test.email" name="email" value="bwayne@wayneenterprise.com" />' +
                '</form>'
            );
            $compile(element)($scope);
            regForm = $scope.regForm;
        }));

        it('should set regForm.email.$error.userExists to true if /doesUserExist returns true', function () {
            $httpBackend.whenPOST('/doesUserExist').respond(defer.resolve(true)); // I'm trying to set the value for 'response' in the .then() for the controller.
            Registration.alreadyRegistered();
            $scope.$digest();
            expect(regForm.email.$error.userExists).toEqual(true);
        });
    });
});

这是我的 authFactory 代码:

angular
    .module('enigma.authFactory', [])    
    .factory('authFactory', authFactory);

authFactory.$inject = ['$http', '$q'];

function authFactory($window, $http, $q, sessionStorageFactory){
    var auth = {
        doesUserExist: doesUserExist
    };

    return auth;

    function doesUserExist(email){
        var defered = $q.defer();
        $http.post('/app/doesUserExist', email)
            .success(function(data){
                if(data.message !== 'user exists'){
                    defered.resolve(false);
                } else {
                    defered.resolve(true);
            }
        });
        return defered.promise;
    }
}

鉴于您完全模拟了您的 authFactory 服务,因此您无需触摸 $httpBackend。只需解析您的模拟返回的 defer 对象。例如

it('should set regForm.email.$error.userExists to true if /doesUserExist returns true', function () {
    Registration.alreadyRegistered();
    expect(doesUserExistSpy).toHaveBeenCalled();

    defer.resolve(true);
    $scope.$apply();

    expect(regForm.email.$error.userExists).toEqual(true);
});