AngularJS + Jasmine如何监视在控制器中调用的服务构造函数

时间:2013-07-24 02:28:08

标签: angularjs service constructor jasmine karma-runner

我正在尝试对我的构造函数进行单元测试。在构造函数中,我正在注入一个包含数据并发出http请求的自定义服务。在我的构造函数的 save 函数中,我通过将构造函数调用到我的自定义服务来实例化作用域上的对象。

我想测试以确保调用我的自定义服务的构造函数。我试图使用茉莉花间谍窥探构造函数调用,但没有成功。我试图按照Jasmine给出的关于如何在构造函数([Jasmine Spies])1上执行间谍的示例,但它不起作用。

我的控制器定义如下:

controller('comments.EditCtrl', ['$scope', '$location', '$routeParams', 'Comment', function($scope, $location, $routeParams, Comment) {

    $scope.save = function(comment) {
        $scope.comment = new Comment(comment);

        $scope.comment.postId = $routeParams.postId;

        Comment.save($scope.comment, function() {
            $location.path('/blog/' + $routeParams.postId);
        });
    };
}])

自定义服务名为“评论”。感兴趣的是

$scope.comment = new Comment(comment);

我无法通过测试来正常工作。我的控制器测试代码如下:

describe('comment.edit', function() {

    beforeEach(function() {
        module('app');
        module('blog.comments');
        module('comments.edit');
    });

    describe('edit controller', function() {
        var $scope, editCtrl, Comment, commentNamespace;

        var mockComment = {
            email: 'spencerdev@maasive.net',
            text: 'mock text'
        };

        beforeEach(inject(function($rootScope, $injector, $controller) {
            var routeParamsStub = jasmine.createSpy('routeParamsStub');
            routeParamsStub.postId = '7';

            Comment = $injector.get('Comment');
            commentNamespace = {
                Comment: Comment
            };
            commentNamespace.Comment.save = function(comment, callback) {
                callback();
                return '';
            };

            $scope = $rootScope.$new();

            editCtrl = $controller('comments.EditCtrl', {
                $scope: $scope,
                $routeParams: routeParamsStub,
                Comment: commentNamespace.Comment
            });
        }));

        it('should have a edit controller', function() {
            expect(editCtrl).not.toBe(null);
            expect(editCtrl).not.toBe(undefined);
        });

        describe('save function', function() {

            beforeEach(function() {
                spyOn(commentNamespace, 'Comment');
                $scope.save(mockComment);
            });

            //TODO: figure out how to spy on Comment constructor call
            it('should create a Comment object via its constructor', function() {
                expect(commentNamespace.Comment).toHaveBeenCalled();
            });
        });
    });
});

你可以看到我正在尝试按照Jasmine的建议创建一个命名空间,然后监视“注释”,希望能够接受构造函数调用。当我运行测试时,我从Karma收到以下错误消息:

[2013-07-23 21:58:47.720] [DEBUG] config - autoWatch set to false, because of singleRun
INFO [karma]: Karma server started at http://localhost:8080/
INFO [launcher]: Starting browser Chrome
INFO [Chrome 28.0 (Mac)]: Connected on socket id QmSDHIAEJnuGEbe8Zmq3
Chrome 28.0 (Mac) LOG: null
Chrome 28.0 (Mac) comment.edit edit controller save function should create a Comment    object via its constructor FAILED
    Expected spy constructor to have been called.
    Error: Expected spy constructor to have been called.
    at null.<anonymous> (/Users/spencer/Projects/angular-blog/src/app/blog/comments/edit/edit.unit.js:68:55)
Chrome 28.0 (Mac): Executed 20 of 20 (1 FAILED) (0.266 secs / 0.092 secs)
Warning: Task "karma:unit" failed. Use --force to continue.

Aborted due to warnings.

我觉得我已经尝试过各种其他策略的组合,例如窥探Comment.prototype.constructor,但我每次都得到相同的消息。有没有人知道如何做到这一点?我知道这里有很多,请告诉我信息中是否有任何漏洞我可能会遗漏一些东西。感谢

1 个答案:

答案 0 :(得分:2)

这是由于茉莉花如何安装间谍。当你说spyOn(foo, 'bar') jasmine用一个行为类似于方法的间谍对象替换bar上的foo属性时。这意味着当你将commentNamespace.Comment传递给你的控制器时,它已经有了对原始构造函数的引用,所以当你spyOn(commentNamespace, 'Comment')之后,它已经太晚了。