2015-11-17 27 views
8

L'unità testare una direttiva angolare non è molto difficile, ma ho scoperto che ci sono diversi modi per farlo.Come testare una direttiva angolare

Ai fini di questo post, lascia supporre la seguente direttiva

angular.module('myApp') 
    .directive('barFoo', function() { 
     return { 
      restrict: 'E', 
      scope: true, 
      template: '<p ng-click="toggle()"><span ng-hide="active">Bar Foo</span></p>', 
      controller: function ($element, $scope) { 
       this.toggle() { 
        this.active = !this.active; 
       } 
      } 
     }; 
    }); 

Ora posso pensare a due modi di prova di unità questo

Metodo 1:

describe('Directive: barFoo', function() { 
    ... 
    beforeEach(inject(function($rootScope, barFooDirective) { 
     element = angular.element('<bar-foo></bar-foo>'); 
     scope = $rootScope.$new(); 
     controller = new barFooDirective[0].controller(element, scope); 
    })); 

    it('should be visible when toggled', function() { 
     controller.toggle(); 
     expect(controller.active).toBeTruthy(); 
    }); 
}); 

Metodo 2 :

beforeEach(inject(function ($compile, $rootScope) { 
    element = angular.element('<bar-foo></bar-foo>'); 
    scope = $rootScope.$new(); 
    $compile(element)(scope); 
    scope.$digest(); 
})); 

it ('should be visible when toggled', function() { 
    element.click(); 
    expect(element.find('span')).not.toHaveClass('ng-hide'); 
}); 

Quindi, sono curioso di sapere quali sono i pro ei contro di entrambi i metodi e quale è il più robusto?

+1

presumo che cliccando su elemento in unità di test è come metodi di controllo di prova a goniometro – Appeiron

risposta

1

Quello che mi piace fare è creare storie del mio test come questo esempio fittizio.

'use strict'; 

describe('app controller', function() { 

    var scope; 

    ... 

    beforeEach(angular.mock.module('MyModule')); 

    it('should have properties defined', function() { 

    expect(scope.user).toEqual(user); 
    ...  

    }); 

    it('should have getFaqUrl method', function() { 

    expect(scope.getFaqUrl).toEqual(refdataService.getFaqUrl); 

    }); 

    it('should signout and delete user data from local storage', function() { 

    ... 

    }); 

}); 

quindi credo che semplicemente non ha precisato in secondo esempio, ma nel caso in cui l'avete fatto, utilizzare descrivere recinto sempre quando si verifica, solo una buona pratica.

Per quanto riguarda il test, consiglierei di evitare il metodo in cui si chiama esplicitamente scope. $ Digest(), soprattutto perché non sembra necessario ai fini del test.

Poco, vorrei andare per il metodo 1.

+0

grazie mille per la risposta. Potresti aggiornare il tuo post con un esempio di come appare il tuo test in combinazione con una storia? –

+0

Mi spiace di averlo modificato solo ora, stavo cercando in qualche esempio fittizio, dato che non posso condividere codice prodotto .. ma questo spiega cosa stavo pensando a shorty, e per ogni controller, aggiungendo una storia come set – desicne

1

trovo il primo metodo più "corretto", perché si pretende molto dipende da un evento di clic. Credo che se vuoi testare il click di un elemento e gli effetti di esso devi usare il goniometro e usare il gelsomino solo per i test unitari. In questo modo avrai una buona separazione tra i test unitari e i test dell'interfaccia utente.

Inoltre rende il test più maintable. per esempio. se decidi di attivare toggle al passaggio del mouse anziché fare clic sul secondo metodo, dovrai aggiornare anche i test.

+0

il primo metodo perché il secondo metodo fa la cosa '.click()'? –

+0

@JeanlucaScaljeri yap, intendevo il primo. L'ho riparato. grazie. –

+0

I test delle unità creati per i metodi di test restituiscono e incidono sui test basati sui dati e sul comportamento (clic, ecc.) Per verificare le interazioni dell'utente reale. – Appeiron

2

Ecco come si prova la vostra direttiva AngularJS:

describe('Directive: barFoo', function() { 
 
    var createElement, element, parentScope, directiveScope; 
 
    
 
    beforeEach(module('myApp')); 
 

 
    beforeEach(inject(function($injector) { 
 
    var $compile = $injector.get('$compile'); 
 
    var $rootScope = $injector.get('$rootScope'), 
 

 
    parentScope = $rootScope.$new(); 
 
    parentScope.paramXyz = ... <-- prepare whatever is expected from parent scope 
 

 
    createElement = function() { 
 
     element = $compile('<bar-foo></bar-foo>')(parentScope); 
 
     directiveScope = element.isolateScope(); 
 
     parentScope.$digest(); 
 
     $httpBackend.flush(); <-- if needed 
 
    }; 
 
    })); 
 

 

 
    it('should do XYZ', function() { 
 
    parentScope.xyz = ... <-- optionnal : adjust scope according to your test 
 
    createElement(); 
 

 
    expect(...) <-- whatever, examples : 
 

 
    var submitButton = element.find('button[type="submit"]'); 
 
    expect(submitButton).to.have.value('Validate'); 
 
    expect(submitButton).to.be.disabled; 
 
    submitButton.click(); 
 
    });

+0

Questo approccio è più o meno lo stesso del metodo 2. Potresti fornire alcune argomentazioni sul motivo per cui è meglio del metodo 1? –

+0

@JeanlucaScaljeri nel metodo 1) devi creare manualmente il controller e nel metodo 2) hai un passaggio in più.L'esempio che propongo (tratto dai nostri test effettivi nella mia azienda) mostra anche una struttura di test che consente un test più semplice, consentendo alcuni extra * prima * di istanziare la direttiva con 'createElement()'. Notare anche la netta separazione tra ambito genitore e figlio. – Offirmo

+0

Mi piace questo approccio. Sono nuovo alle direttive di prova. Mi chiedo come si identifica una direttiva specifica da testare? È necessario? – Winnemucca

Problemi correlati