8

Sto provando a scrivere un test unitario che verifica che venga chiamato $rootScope.$broadcast('myApiPlay', { action : 'play' });.

Ecco l'myapi.js

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

E qui è la mia prova Unità:

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'); 
    }); 
}); 

Qui è l'errore che sto ottenendo durante l'esecuzione 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. 

Ho anche provato con expect(rootScope.$broadcast).toHaveBeenCalled() e sto avendo un errore simile: Expected spy $broadcast to have been called..

Vorrei verificare che tale metodo sia stato effettivamente chiamato con i parametri corretti.

Grazie!

+0

Avete solo bisogno di cambiare l'ordine? Potresti dover aspettare prima che venga effettivamente chiamato, nel tuo caso lo chiami, quindi aspettati. Puoi anche confermare il conteggio delle chiamate. – hassassin

+0

Ho cambiato l'ordine, lo stesso errore. – Andrea

risposta

14

Il motivo per cui i test non sono di passaggio è perché si sta spiando la funzione $ trasmissione sbagliata. Nel setup beforeEach, si chiede di avere il rootScope $ iniettato e quindi si crea un scope child chiamando $ rootScope. $ New().

Il valore di ritorno da $ rootScope. $ New() non è più il rootScope ma un figlio dell'ambito di base.

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; 
    }) 
}); 

Nella funzione di riproduzione, si chiedono $ onda su $ rootScope ma nel tuo test che si stanno spiando su un bambino di $ rootScope.

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

Quindi, per avvolgerlo, rimuovere la chiamata a $ rootScope. $ New() e solo spiare il $ rootScope l'iniettore vi ha dato. $ RootScope fornito per il test della tua unità è lo stesso $ rootScope fornito per il tuo servizio API, quindi dovresti spiare direttamente su $ rootScope.

Scopri i plunkr http://plnkr.co/edit/wN0m8no2FlKf3BZKjC4k?p=preview

+2

questo va bene per 'expect (rootScope. $ Broadcast) .toHaveBeenCalledWith ('myApiPlay', {action: 'play'});' ma questo expect non è chiamato: 'rootScope. $ On ('myApiPlay', function (evento , dati) {expect (data.action) .toBe ('play');}); ' – Andrea

+1

non hai bisogno di quel test. Quel test sta testando la struttura angolare e non la logica aziendale stessa. Si può presumere che quando si chiama rootScope. $ Broadcast, l'impostazione dei listener usando $ on verrà chiamata correttamente perché questo è il modo in cui AngularJS funziona – jcruz

+0

tutto ciò che è realmente necessario testare è $ rootScope.$ broadcast è stato chiamato con i parametri attesi – jcruz

1

Sarà utile per voi https://stackoverflow.com/a/17227264/2594499 Il test non è chiaro. Evita di usare "expect" in condizioni, callback e cose come questa. Se la tua condizione non sarà vera, avrai una prova senza affermazione.

Sarà meglio usare secondo parametro della funzione:

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

Ciao, sto facendo come stai dicendo, ma il test unitario dice che non viene chiamato. Sto testando che quando viene chiamato 'MyApi.play()' viene chiamato il messaggio viene trasmesso. – Andrea