Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Angularjs 带位置侦听器的单元测试$q(角度)_Angularjs_Unit Testing - Fatal编程技术网

Angularjs 带位置侦听器的单元测试$q(角度)

Angularjs 带位置侦听器的单元测试$q(角度),angularjs,unit-testing,Angularjs,Unit Testing,我有一个控制器可以做两件事: 1) 履行承诺时执行函数($q.then) 2) 在触发'onLocationChangedStart'事件时执行函数 在我的单元测试中,我想测试(1)的功能。我通过执行$RootScope.$apply()来触发承诺解析。不幸的是,$rootScope.$apply()也会发出一个'onLocationChangedStart'事件,其中url=http://server/(这在角度代码内) 显然这是一个问题,因为它将触发(2),尽管这不是我在这个特定单元测试中想

我有一个控制器可以做两件事:

1) 履行承诺时执行函数($q.then)

2) 在触发
'onLocationChangedStart'
事件时执行函数

在我的单元测试中,我想测试(1)的功能。我通过执行
$RootScope.$apply()
来触发承诺解析。不幸的是,
$rootScope.$apply()
也会发出一个
'onLocationChangedStart'
事件,其中url=
http://server/
(这在角度代码内)

显然这是一个问题,因为它将触发(2),尽管这不是我在这个特定单元测试中想要的

有没有简单的方法不需要修改原始代码来运行单元测试?(例如,我可以将函数(2)放在
$scope
上,然后在运行测试之前将其模拟为null。但这似乎有点太草率了)

更新为删除的代码示例:

angular.module('myMod')

.controller("ctrl", function ($scope, $log, myService, $location) {

     myService.doSomething()
           .then(function () {
               //does something

           })

       })


    $scope.$on('$locationChangeStart', routeChange);

    function routeChange(event, currentUrl, nextUrl) {
           //does something
    };

})

//Jasmine unit test
describe('test', function () {
    var $scope,
         ctrl,
         $rootScope;


    beforeEach(function () {

        module("myMod");
          module("myServiceMock");


        inject(function (_$rootScope_, $controller, _myService_) {
            $rootScope = _$rootScope_;
            $scope = $rootScope.$new();


            ctrl = $controller('ctrl', {
                $scope: $scope

            });


        });
    });


    it("Should set startup values appropriately", inject(function () {

        //doing this triggers both the myService promise AND the location event listener
        $rootScope.$apply();



}));

您可以使用
$scope.$digest()
而不是
$scope.$apply()
$digest()
只在当前作用域上执行关注的表达式,而
$apply()
运行
$rootScope.$digest()


您应该模拟事件触发函数或承诺解析函数。这是单位的正常做法tests@Alp-但这不意味着我必须将其中一个函数放在$scope上吗?这意味着向视图提供它不需要的东西。如果这是真的,那就是为什么我认为它是“哈基什”,不想沿着这条路走下去。我不知道您的应用程序看起来如何,但它可能类似于模拟$http或$resource服务。我不能在没有看到问题的情况下给出进一步的建议code@Alp-好,添加了代码。我想我可以做的一件简单的事情是将侦听器分离函数放在$scope上,而不是放在完整函数本身上。类似于:$scope.onRouteChangeOff=$scope.on(“$locationChangeStart”,routeChange);然后在我的单元测试中调用$apply之前调用onRouteChangeOff。还是感觉不对,真不错!添加清晰解释其工作原理的奖励:)
it("Should set startup values appropriately", function() {
   $scope.$digest();
   // promise resolved
   // onLocationChangedStart event not fired
});