angularjs 使用 jasmine 进行测试 - $httpBackend 没有给我正确的行为

angularjs testing with jasmine - $httpBackend not giving me the right behavior

这是我的控制器:

rcCtrls.controller('LoginController', [
'$scope', 
'AuthService',
function($scope, AuthService)
{
    console.log('LoginController');
    $scope.credantials = {
            email:      '',
            password:   '',
            remember:   false
    }
    $scope.login = function(credantials)
    {
        console.log('before login');
        AuthService.login(credantials.email, credantials.password, credantials.remember || false).success(function(response) {
            console.log('login successful');
            console.log(response);
            location.reload();
        }).error(function() {
            console.log('failed to login');
        });
    };
}]);

这是我的 AuthService:

rcServices.factory('AuthService', [
'$http',
function($http) 
{ 
    return {
        login: function(email, password, remember) {
            console.log('Auth Service Login');
            return $http.post('/auth/login', {email: email, password: password, remember: remember});
        },
        logout: function() {
            return $http.post('/auth/logout');
        }
    };
}]);

这是我的规格:

describe('Controller: LoginController', function() {
    // We initiate the app moudle mock
    beforeEach(module('app')); // alias for angular.mock.module('app')

    beforeEach(inject(function($controller, $rootScope, AuthService, $httpBackend){
        this.$httpBackend = $httpBackend;
        this.scope = $rootScope.$new();
        $controller('LoginController', {
            $scope: this.scope,
            AuthService: AuthService
        });
    }));

    describe("checking credantials at the begining", function() {
        it("should be initiated", function() {
            expect(this.scope.credantials).toEqual({ email: '', password: '', remember: false });
        });
    });

    describe("successfully logged in", function() {
        it("should redirect to home", function() {
            this.scope.credantials = { email: 'test@mail.com', password: '123', remember: false };
            this.$httpBackend.expectPOST('/auth/login', this.scope.credantials).respond(200, {test: 'test'});
            this.scope.login(this.scope.credantials);
            console.log(this);
            this.$httpBackend.flush();
            expect(this.scope).toBeDefined();
        });
    });

});

似乎 $httpBackend 没有做它应该做的事情。

我确实得到了所有控制台日志,直到我的服务使用 $http post 请求的那一刻,然后它停止了。

仅供参考,我的控制器在应用程序本身上正常工作! post 正在发生并且响应正在正确返回。

但是测试并没有...

我遇到错误: Error: No pending request to flush ! 评论它没有帮助。

编辑:

问题出在我的 angular-mock.js 版本上....真可悲。

在您的服务中您调用:

        location.reload();

这可能会干扰 jasmine 并导致不可预测的行为。这个调用有什么作用,你需要它吗?如果你把它注释掉,你的测试会发生什么?

如果你真的需要进行那个调用,你应该使用AngularJS内置的$location服务并模拟它,这样你就可以保持行为但不破坏茉莉花正在处理中。

===========

更新:

此外,您使用 this.httpBackend 有点奇怪,而通常情况下您会完全覆盖引用 - 不是将其作为 this 的属性存储,而是作为测试的全局变量存储。我怀疑您已经在应用程序的其他地方调用了 flush 并且引用未正确重置。你有任何其他调用 flush 的测试吗?

http://plnkr.co/edit/jBewavvO1n8NBa6WGFja

我在这个 plunkr 中进行了工作测试,它按原样通过了你的代码。除了我注释掉的 location.reload() 行之外,它并没有破坏测试,尽管这个测试运行器与它在 plunkr 中的有点不同,而且情况并非总是如此。你真的不应该在测试中调用它。