包含promises的函数的单元测试未按预期工作

时间:2014-09-10 17:48:23

标签: angularjs unit-testing jasmine

我试图对处理用户签名的控制器进行单元测试。我收到错误并认为它可能与使用promises的代码有关但我并不是真的确定在这一点上。这是控制器。

angular.module('app').controller('SignIn', SignIn);

function SignIn ($scope, $state, auth) {

    $scope.credentials = {};

    // signin
    $scope.signIn = function () {
        auth.signIn($scope.credentials)
            .then(function () {
                $state.go('user.welcome');
            }, function (res) {
                $scope.signInError = res.statusText;
            });
    };
}

这是授权服务。

angular.module('app').factory('auth', auth);

function auth (session, api) {
    return {
        signIn : function (credentials) {
            return api.signIn(credentials)
                .then(function (res) {
                    session.create(res.data.sessionId, res.data.userName);
                });
        },
        signout: function () {
            return session.destroy();
        },
        isAuthenticated: function () {
            return !!session.userName;
        }
    };
}

api只返回$ http promises。

signIn : function (credentials) {
    return $http.post(base + '/auth/credentials', credentials);
}

会话只是一个存储当前会话信息的工厂,并将其保存到浏览器的cookie中。

这是我的茉莉花测试

describe('SignIn', function () {

// setup ------------------------------------------------------------------

    // init app module
    beforeEach(module('app'));

    // inject Session service
    beforeEach(angular.mock.inject(function (_$rootScope_, _$controller_, _auth_) {
        $rootScope             = _$rootScope_;
        $scope                 = $rootScope.$new();
        controller             = _$controller_("SignIn", {$scope: $scope});
        auth                   = _auth_;
    }));

    // setup spies
    beforeEach(function () {
        spyOn(auth, 'signIn');
    });

// tests ------------------------------------------------------------------

    // signin in
    it("should call auth.signIn with the user's credentials", function () {
        $scope.signIn();
        expect(auth.signIn).toHaveBeenCalled();
    });

});

我只是试图测试当你调用$ scope.signIn()时调用auth.signIn。应用程序本身工作但我在尝试运行此测试时遇到此错误。

SignIn should call auth.signIn with the user's credentials FAILED
TypeError: 'undefined' is not an object (evaluating 'auth.signIn($scope.credentials).then')

尽管存在期望,但当我调用$ scope.signIn()时会发生错误。如果我在$ scope.signIn()之前记录auth;被称为我得到这个。

LOG: Object{signIn: function () { ... }, signout: function () { ... }, isAuthenticated: function () { ... }}

所以我假设DI正在按预期工作。我已经看过不同的设置间谍的方法,但还没有弄明白实际上还有什么问题。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

这是因为你正在监视auth的{​​{1}}功能。当你监视它时,它不再是你在api中的真正功能了。因此,您需要使用.and.returnValue发送来自间谍的承诺。

所以: -

signIn

<强> Plnkr

如果你要为signIn(或任何其他函数的承诺,只做)返回一些值

beforeEach(inject(function (_$rootScope_, _$controller_, _auth_, _$q_) {
    $rootScope             = _$rootScope_;
    $scope                 = $rootScope.$new();
    controller             = _$controller_("SignIn", {$scope: $scope});
    auth                   = _auth_;
    fakePromise = _$q_.when(); //get a fake promise
}));

beforeEach(function () {
  spyOn(auth, 'signIn').and.returnValue(fakePromise); //return fakepromise
});