8

Tôi đang cố gắng viết một bài kiểm tra đơn vị xác minh rằng $rootScope.$broadcast('myApiPlay', { action : 'play' }); được gọi.

Đây là myapi.js

angular.module('myApp').factory('MyApi', function ($rootScope) { 
    var api = {}; 
    api.play = function() { 
     $rootScope.$broadcast('myApiPlay', { action : 'play' }); 
    } 
    return api; 
}); 

Và đây là Unit Test của tôi:

describe('Service: MyApi', function() { 

    // load the service's module 
    beforeEach(module('myApp')); 

    // instantiate service 
    var MyApi; 
    var rootScope; 

    beforeEach(function() { 
     inject(function ($rootScope, _MyApi_) { 
      MyApi = _MyApi_; 
      rootScope = $rootScope.$new(); 
     }) 
    }); 
    it('should broadcast to play', function() { 
     spyOn(rootScope, '$broadcast').andCallThrough(); 
     rootScope.$on('myApiPlay', function (event, data) { 
      expect(data.action).toBe('play'); 
     }); 
     MyApi.play(); 
     expect(rootScope.$broadcast).toHaveBeenCalledWith('myApiPlay'); 
    }); 
}); 

Đây là lỗi tôi nhận được khi chạy grunt test:

PhantomJS 1.9.7 (Windows 7) Service: MyApi should broadcast to pause FAILED 
     Expected spy $broadcast to have been called with [ 'myApiPlay' ] but it was never called. 

Tôi cũng đã thử với expect(rootScope.$broadcast).toHaveBeenCalled() và tôi gặp lỗi tương tự: Expected spy $broadcast to have been called..

Tôi muốn xác minh rằng phương thức đó thực sự đã được gọi với thông số phù hợp.

Cảm ơn bạn!

+0

Bạn chỉ cần chuyển đơn đặt hàng? Bạn có thể cần phải mong đợi trước khi nó thực sự được gọi, trong trường hợp của bạn, bạn gọi nó, sau đó mong đợi nó. Bạn cũng có thể xác nhận số cuộc gọi đó. – hassassin

+0

Tôi đã chuyển lệnh, cùng một lỗi. – Andrea

Trả lời

14

Lý do kiểm tra bạn không chuyển là bởi vì bạn đang gián điệp vào chức năng $ phát sóng sai. Trong thiết lập beforeEach của bạn, bạn yêu cầu có $ rootScope được tiêm và sau đó bạn tạo một phạm vi con bằng cách gọi $ rootScope. $ New().

Giá trị trả về từ $ rootScope. $ New() không còn là rootScope mà là con của phạm vi gốc.

beforeEach(function() { 
    //inject $rootScope 
    inject(function ($rootScope, _MyApi_) { 
     MyApi = _MyApi_; 
     //create a new child scope and call it root scope 
     rootScope = $rootScope.$new(); 
     //instead don't create a child scope and keep a reference to the actual rootScope 
     rootScope = $rootScope; 
    }) 
}); 

Trong chức năng phát của bạn, bạn đang gọi $ phát sóng trên $ rootScope nhưng trong thử nghiệm bạn đang theo dõi con của $ rootScope.

$rootScope.$broadcast('myApiPlay', { action : 'play' }); 

Vì vậy, để kết thúc nó, hãy xóa cuộc gọi đến $ rootScope. $ New() và chỉ cần theo dõi $ rootScope máy in đã cấp cho bạn. $ RootScope được cung cấp cho thử nghiệm đơn vị của bạn giống $ rootScope được cung cấp cho dịch vụ API của bạn, do đó bạn nên theo dõi trực tiếp trên $ rootScope.

Kiểm tra các plunkr http://plnkr.co/edit/wN0m8no2FlKf3BZKjC4k?p=preview

+2

điều này là tốt cho 'mong đợi (rootScope. $ Phát sóng) .toHaveBeenCalledWith ('myApiPlay', {action: 'play'});' nhưng điều này mong đợi không được gọi là: 'rootScope. $ On ('myApiPlay', function (event) , dữ liệu) {expect (data.action) .toBe ('play');}); ' – Andrea

+1

bạn không cần thử nghiệm đó. Bài kiểm tra đó đang thử nghiệm khuôn khổ góc cạnh và không phải là logic nghiệp vụ. Bạn có thể giả định rằng khi bạn gọi rootScope. $ Broadcast, thiết lập người nghe sử dụng $ on sẽ được gọi chính xác vì đó là cách AngularJS hoạt động – jcruz

+0

tất cả những gì bạn thực sự cần kiểm tra là $ rootScope.$ broadcast được gọi với các tham số dự kiến ​​ – jcruz

1

Điều này sẽ hữu ích cho bạn https://stackoverflow.com/a/17227264/2594499 Bài kiểm tra của bạn không rõ ràng. Tránh sử dụng "mong đợi" trong điều kiện, gọi lại và những thứ như thế này. Nếu tình trạng của bạn không đúng, bạn đã được kiểm tra mà không cần khẳng định.

Nó sẽ được tốt hơn để sử dụng tham số thứ hai của hàm:

.toHaveBeenCalledwith('someEvent', someObj); 
+0

Xin chào, tôi đang làm như bạn đang nói, nhưng bài kiểm tra đơn vị nói rằng nó không được gọi. Tôi đang thử nghiệm khi gọi 'MyApi.play()' được gọi là thông điệp được phát sóng. – Andrea

Các vấn đề liên quan