0

我在调用实际实现时遇到了问题,我收到了这个错误:

TypeError: undefined is not an object (evaluating 'GitUser.GetGitUser('test').then') ...

这是我的代码:

app.controller('HomeController', ['$scope', 'GitUser', function ($scope, GitUser) {
    $scope.name = "user";

    GitUser.GetGitUser('test').then(function (data) {
        console.log(data);
        if (data) {
            $scope.name = data;
        }
    });
}]);
app.factory('GitUser', function ($http) {
    return {
        GetGitUser: function (username) {
            return $http.get('https://api.github.com/users/' + username)
            .then(function success(response) {
                return response.data.login;
            });
        }
    };
});

这是我的单元测试:

describe('HomeController Unit Test', function () {
    var $controllerConstructor, scope;

    beforeEach(module("AngularApp"));

    beforeEach(inject(function ($controller, $rootScope) {
        $controllerConstructor = $controller;
        scope = $rootScope.$new();
    }));

    it('should test if scope.name is test', function () {
        // Act
        GitUser = {
            GetGitUser: function () { }
        };

        spyOn(GitUser, "GetGitUser").and.callThrough();

        GitUser.GetGitUser();

        $controllerConstructor('HomeController', {
            '$scope': scope,
            'GitUser': GitUser
        })

        // Assert
        expect(GitUser.GetGitUser).toHaveBeenCalled();
        expect(scope.name).toBe('test');
    });
});
4

2 回答 2

2

这个问题比缺少注入要复杂一些......这是一个调整后的测试:

https://plnkr.co/edit/ZMr0J4jmLPtDXKpRvGBm?p=preview

有一些问题:1)您正在测试一个返回承诺的函数 - 所以您还需要以这种方式模拟它($q.when(..)例如使用 return )。

2)您正在尝试测试创建控制器时发生的代码 -

GitUser.GetGitUser('test').then(function (data) {
        console.log(data);
        if (data) {
            $scope.name = data;
        }
    });

应该包装在一个函数中:

function init() {
 GitUser.GetGitUser('test').then(function (data) {
        console.log(data);
        if (data) {
            $scope.name = data;
        }
    });
}

然后在您的范围内提供它:

scope.init= init;

然后在您的测试中调用该函数并验证您的断言。如果你不将它包装在一个函数中,它将无法测试。

此外 - 模拟和 callThrough 的事情......当您测试控制器(而不是服务)时,您可以使用 callFake 代替 - callFake 函数可以返回一个带有值的 Promise(您稍后要验证的那个) -那么您可以确保拼图的控制器部分正常工作。

  var name = 'test';
    // instead of trying to mock GitUser you can just callFake and be sure to return a promise
    spyOn(GitUser, "GetGitUser").and.callFake(function() {
      return $q.when(name);
    });

我希望这一切都是有道理的——plunker 应该把事情说清楚——我会在那里添加更多评论。

于 2017-01-14T02:29:41.273 回答
0

我想你只是在这里错过了一些东西

beforeEach(inject(function ($controller, $rootScope, _GitUser) {
    $controllerConstructor = $controller;
    scope = $rootScope.$new();
    GitUser = _GitUser;
}));
于 2017-01-14T01:56:07.690 回答