使用andCallThrough()后,在每个测试用例后重置broadcast()

Max*_*Max 5 unit-testing angularjs karma-jasmine

$broadcast在每个测试用例之后使用下面的代码重置,但它似乎$rootScope.$broadcast.reset();无法正常工作,因为测试波纹管应该返回1,但它返回6.

似乎原因是andCallThrough(),因为在我使用它之前没有andCallThrough()函数,但是在一些重构之后它给了我一个错误TypeError: Cannot read property 'defaultPrevented' of undefined,所以我不得不用来防止这个错误.

问题是我如何重置broadcast使用时间andCallThrough或是否有另一种更精确的方法?

beforeEach(function() {
   spyOn($http, 'post');
   spyOn($rootScope, '$broadcast').andCallThrough();
});

afterEach(function() {
   $http.post.reset();
   $rootScope.$broadcast.reset();
});

it('should make a POST request to API endpoint', function() {
   $http.post.andCallThrough();
   var response = { id: '123', role: 'employee', email: 'user@email.com', username: 'someUsername' };
   $httpBackend.expectPOST(apiUrl + 'login').respond(response);
   service.login();
   $httpBackend.flush();
   $timeout.flush();
   expect($rootScope.$broadcast.callCount).toBe(1);
   expect($rootScope.$broadcast).toHaveBeenCalledWith(AUTH_EVENTS.loginSuccess, response);
});
Run Code Online (Sandbox Code Playgroud)

Max*_*Max 4

经过长时间调查在这种情况下事情是如何工作的,最终测试通过了,解决方案是当前的:

问题不在于重置broadcast(),或者reset在使用andCallThrough() 时每个测试用例后未调用方法。问题是 是$rootScope.$broadcast.andCallThrough();由其他事件触发的并且.callCount()函数返回了6,这基本上意味着$broadcast间谍被调用了 6 次。就我而言,我只对事件感兴趣AUTH_EVENTS.loginSuccess,并确保它只广播一次。

expect($rootScope.$broadcast.callCount).toBe(1);
expect($rootScope.$broadcast).toHaveBeenCalledWith(AUTH_EVENTS.loginSuccess, response);
Run Code Online (Sandbox Code Playgroud)

因此,挖掘 的方法$rootScope.$broadcast.calls给了我所有调用的数组,应该从中检索上面两个期望的调用。因此,解决方案是:

it('should make a POST request to API endpoint', function() {
  $http.post.andCallThrough();
  var response = { id: '123', role: 'employee', email: 'user@email.com', username: 'someUsername' };
  $httpBackend.expectPOST(apiUrl + 'login').respond(response);
  service.login();
  $httpBackend.flush();
  $timeout.flush();

  var loginSuccessTriggerCount = _($rootScope.$broadcast.calls)
    .chain()
    .map(function getFirstArgument(call) {
      return call.args[0];
    })
    .filter(function onlyLoginSuccess(eventName) {
      return eventName === AUTH_EVENTS.loginSuccess;
    })
    .value().length;

  expect(loginSuccessTriggerCount).toBe(1);
});
Run Code Online (Sandbox Code Playgroud)