如何通过单元测试控制器来避免错误?

时间:2015-07-28 06:12:13

标签: angularjs unit-testing jasmine

我正在尝试对控制器进行单元测试。这是我的控制者:

app.factory('myService', function ($q) {
    var callMe = function (user) {
        var pr = $q.defer();
        pr.resolve('Hello ' + user);
        return pr.promise;

        //$timeout(function(){
        //    pr.resolve('Hello ' + user);
        //    return pr.promise;
        //},4000);

    }
    return {callMe: callMe};
});



app.controller('myCtrl',function($scope,myService){
    $scope.callService = function(){
        $scope.callMeValue = myService.callMe('lo');
    }
})

这是我的测试:

beforeEach(
    inject(function (_$rootScope_, $controller, _myService_, _myServiceTimeout_,$q) {
    myService = _myService_;
    myServiceTimeout = _myServiceTimeout_;
    $scope = _$rootScope_.$new();

    ctrl = $controller('myCtrl', {
        $scope: $scope,
        someService: someServiceMock
    });

    someServiceMock.callMe.andReturn($q.when('Ted'));
}));


it('ctrl test', function () {
    $scope.callService();
    expect(myService.callMe).toHaveBeenCalled();
});

以下是我遇到的错误:

TypeError: someServiceMock.callMe.andReturn is not a function

Error: Expected a spy, but got Function.

我该如何解决这个问题?

plunkr:http://plnkr.co/edit/EM1blTOlg5fw5wq6OFcr?p=preview

1 个答案:

答案 0 :(得分:1)

您的示例包含多个错误。

  1. 如果在代码中使用超时,则在测试中必须使用$ timeout.flush()(范围。$ apply not enough)
  2. $ timeout是承诺,你不需要创建自己的承诺
  3. $ timeout是承诺,你必须退回

    app.factory('myServiceTimeout', function ( $timeout) {
        var callMe = function (user) {
            return $timeout(function(){
                return 'Hello ' + user;
            },4000);
    
        }
        return {callMe: callMe};
    });
    
    
    it('test2',function(){
        var result;
        myServiceTimeout.callMe('Ruud').then(function(ret)
        {
            result = ret;
        });
    
        $timeout.flush()
        expect(result).toBe('Hello Ruud');
    });
    
  4. 整个例子:http://plnkr.co/edit/cqzTYwfs94Xqyz5MTxeE?p=preview