测试Angular $ emit和$ on事件

时间:2020-12-06 00:09:17

I am trying to write unit test for my events in controller.

我正在尝试为控制器中的事件编写单元测试。

Below is my controller

下面是我的控制器

myApp.controller('ParentCtrl', ['$scope', function ($scope) {
    $scope.message = "Some text in parent";
    $scope.$on("update_parent_controller", function(event, message){
        $scope.message = message;
    });

}])
.controller('ChildCtrl', ['$scope', function ($scope) {
    $scope.clickFunction = function() {
    $scope.message = "Parent updated from child controller";

        $scope.$emit('update_parent_controller', $scope.message);
    }

}]);

And below is my test that i am trying to write

以下是我试图写的测试

describe("Hello Controller Test", function () {
    var ctrl, scope;

    beforeEach(module("myApp"));

    beforeEach(inject(function ($controller, $rootScope) {
        scope = $rootScope.$new();
        spyOn(scope, '$on');

        ctrl = $controller("ParentCtrl", {
            $scope : scope
        });
    }));

    it('should change ParentCtrl message property from child ctrl', function (){

        var new_hero = 'Ralf ninja turtle',
            sub_scope = scope.$new();

        sub_scope.$emit('update_parent_controller', new_hero);

        expect(scope.$on).toHaveBeenCalled();
        expect(scope.message).toBe('Ralf ninja turtle'); //Getting err here
    });
});

I am expecting message in the parent controller to be updated, But the test is failing at expect(scope.message).toBe('Ralf ninja turtle');

我希望更新父控制器中的消息,但是测试是在期望失败(scope.message).toBe('Ralf ninja turtle');

2 个解决方案

#1


0  

In the test case scope.$on was spied on.

在测试用例范围内,$ on被监视。

spyOn(scope, '$on');

In order to call the actual function, .and.callThrough() must be added.

为了调用实际函数,必须添加.and.callThrough()。

spyOn(scope, '$on').and.callThrough();

Here is a full working example:

这是一个完整的工作示例:

angular.module('myApp', []).controller('ParentCtrl', ['$scope', function ($scope) {
    $scope.message = "Some text in parent";
    $scope.$on("update_parent_controller", function(event, message){
        $scope.message = message;
    });
}]);

describe("Hello Controller Test", function () {
    var ctrl, scope;

    beforeEach(module("myApp"));

    beforeEach(inject(function ($controller, $rootScope) {
        scope = $rootScope.$new();
        spyOn(scope, '$on').and.callThrough();  // <-- This is the fix

        ctrl = $controller("ParentCtrl", {
            $scope : scope
        });
    }));

    it('should change ParentCtrl message property from child ctrl', function (){

        var new_hero = 'Ralf ninja turtle',
            sub_scope = scope.$new();

        sub_scope.$emit('update_parent_controller', new_hero);

        expect(scope.$on).toHaveBeenCalled();
        expect(scope.message).toBe('Ralf ninja turtle'); //Getting err here
    });
});
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.3.4/jasmine.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.3.4/jasmine.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.3.4/jasmine-html.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.3.4/boot.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.6/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.6/angular-mocks.js"></script>

#2


1  

You need to call $scope.$apply() after the call to $emit. This would happen automatically in the application, but needs to be called explicitly in the test.

调用$ emit后需要调用$ scope。$ apply()。这将在应用程序中自动发生,但需要在测试中明确调用。

#1


0  

In the test case scope.$on was spied on.

在测试用例范围内,$ on被监视。

spyOn(scope, '$on');

In order to call the actual function, .and.callThrough() must be added.

为了调用实际函数,必须添加.and.callThrough()。

spyOn(scope, '$on').and.callThrough();

Here is a full working example:

这是一个完整的工作示例:

angular.module('myApp', []).controller('ParentCtrl', ['$scope', function ($scope) {
    $scope.message = "Some text in parent";
    $scope.$on("update_parent_controller", function(event, message){
        $scope.message = message;
    });
}]);

describe("Hello Controller Test", function () {
    var ctrl, scope;

    beforeEach(module("myApp"));

    beforeEach(inject(function ($controller, $rootScope) {
        scope = $rootScope.$new();
        spyOn(scope, '$on').and.callThrough();  // <-- This is the fix

        ctrl = $controller("ParentCtrl", {
            $scope : scope
        });
    }));

    it('should change ParentCtrl message property from child ctrl', function (){

        var new_hero = 'Ralf ninja turtle',
            sub_scope = scope.$new();

        sub_scope.$emit('update_parent_controller', new_hero);

        expect(scope.$on).toHaveBeenCalled();
        expect(scope.message).toBe('Ralf ninja turtle'); //Getting err here
    });
});
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.3.4/jasmine.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.3.4/jasmine.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.3.4/jasmine-html.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.3.4/boot.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.6/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.6/angular-mocks.js"></script>

#2


1  

You need to call $scope.$apply() after the call to $emit. This would happen automatically in the application, but needs to be called explicitly in the test.

调用$ emit后需要调用$ scope。$ apply()。这将在应用程序中自动发生,但需要在测试中明确调用。