Angular.js单元测试运行阶段发生的事情(rootScope事件监听)

时间:2013-12-31 11:03:33

标签: angularjs

我必须在rootScope上(也欢迎建议)一个关于stateChangeError事件的监听器,它会重新路由它们以进行错误处理。 类似的东西:

$rootScope.$on('$stateChangeError', function(event, toState, toParams, fromState, fromParams, error){
          if(error.status === 404 ){
              event.preventDefault();
              $state.go('404');
          } else if(error.status === 500){
              event.preventDefault();
              $state.go('500');
          }

      });

我无法找到如何在单元测试中访问运行阶段?对特定听众进行单元测试? 我想测试是否调用$state.go

我会感谢帮助/建议 - 谢谢!

1 个答案:

答案 0 :(得分:1)

如果你想测试Angular调用$state.go(),那么你正在编写集成测试,如果框架不支持这种类型的测试(我不确定它是否存在),这可能会很棘手。

通常要解决此类问题,我使用以下技巧:

  1. 我测试的是函数,而不是监听器。
  2. 我测试此函数是否已在侦听器中正确注册。
  3. 在我向你描述之前,请稍微改变主意,忘记这个匿名功能 function(event, toState, toParams, fromState, fromParams, error){...},只需 - 将其命名为var myLogic = function (event, toState, toParams, fromState, fromParams, error){...} 你能看到区别么?您不再拥有匿名回调,现在您拥有自己的逻辑,必须进行测试。

    现在,如果你专注于单元测试,那么你对测试Angular的监听器机制是否按预期工作并不感兴趣。您要测试的是被触发的函数执行它需要做的事情,即调用$state.go()。因此,既然您现在拥有myLogic功能,那么您现在可以根据需要进行测试!

    // --------- Real class ---------
    var myLogic = function(component1, component2) {
       component1.do();
    }
    
    $rootScope.$on("event", myLogic);
    
    // --------- Tests pseudocode ---------
    
    // Test that your logic does what it is supposed to be doing
    
    // When
    myLogic(comp1Mock, comp2Mock);
    // Then
    expect(comp1.do).toHaveBeenCalled();
    
    // Test that your logic was attached to proper place in the framework. 
    // To do that, you have to mock part of the framework. Fortunately in 
    // Angular all parts of framework component/services are injected to 
    // a controller.
    
    // When - your controller is initialized
    // Then
    expect(rootScopeMock.on).toHaveBeenCalledWith("event", myLogic);
    

    瞧!