2015-07-31 12 views
8

Ho gamma XF: var xf = []; E ho una funzione è un elemento in questo array e una funzione di usarlo:Come creare unit test per la funzione di matrice in AngularJS con Jasmine

$scope.checkEmailValid = function() { 
    var result = false; 
    Iif (xf.validateEmail($scope.email, '256')) { 
    result = true; 
    } 
    return result; 
}; 

xf.validateUsername = function (sText) { 
    var isValid = false; 
    do { 
    //Check for valid string. 
    isValid = typeof sText === 'string'; 
    if (!isValid) { 
     break; 
    } 
    //Check that each special character does not exist in string. 
    for (var i = 0; i < sText.length; i++) { 
     if (xf.SPECIAL_CHARS.indexOf(sText.charAt(i)) !== -1) { 
     isValid = false; 
     break; 
     } 
    } 
    if (!isValid) { 
     break; 
    } 
    } while (false); 
    return isValid; 
}; 

Ma quando eseguo il mio spec:

it ('checkEmail', function(){ 
    $controller('MyCtrl', { $scope: $scope }); 
    xf.validateUsername(); 
    spyOn(window,xf.validateUsername).and.callThrough(); 
}); 

Si fa un errore:

xf.validateUsername is not a function

Come posso cove è vero?

+0

è 'xf' una proprietà su' $ scope', una proprietà sul controller o solo una variabile in formato libero nel corpo della funzione controller? – Claies

+0

@Claies: xf è solo una variabile in formato libero nel corpo del controller. –

+1

non è possibile testarlo in questo modo. Se non è effettivamente associato a '$ scope' o esposto come proprietà pubblica, è accessibile solo nella funzione definita, a causa del modo in cui operano le chiusure JavaScript. – Claies

risposta

0

Non sono sicuro di comprendere completamente la tua domanda. Ma ci sono alcuni pensa penso che si sta facendo male:

  • Se XF è una variabile globale si dovrebbe prendere in giro, dal momento che si sta testando il controller, non è la variabile globale.
  • Se si desidera controllare la reale funzione della variabile globale, passare al file karma.conf.js e aggiungere il percorso del file js all'opzione files:

    files: [ ..., 'fx-script.js', ... ],

  • callThrough dovrebbe essere usato prima del vero e proprio funzione viene richiamata:

    it ('checkEmail', function(){ var ctrl = $controller('MyCtrl', { $scope: $scope }); spyOn(window, ctrl.xf.validateUsername).and.callThrough(); ctrl.xf.validateUsername(); });

Ti consiglio di testare separatamente il tuo controller, service o gli script globali e di aggiungere mock ogni volta che è necessario iniettare una dipendenza o una variabile globale, quindi se puoi dire con certezza quale module/script ha esito negativo in qualsiasi momento.

+0

Ciao @Matho. Sì, sto testando il controller. xf è una variabile locale in questo controller. 'var xf = []'. E la funzione 'validateUsername()' è insieme nel file con l'array xf. Ho scritto il tuo codice, ma è un errore di errore: 'TypeError: Impossibile leggere la proprietà 'validateUsername' di undefined' –

+1

In questo caso il problema è che dovresti fare un'esposizione della funzione' validateUsername' nel 'ctrl.scope' proprio come lo stai facendo con '$ scope.checkEmailValid'. È possibile e deve solo testare le funzioni pubbliche che sono esposte dal controller. _Esempio: _ Se il controller ha una 'funzione A',' funzione B' nel loro campo di applicazione, e la funzione B chiama la 'funzione C', in tal caso è necessario testare A e B e vedere i risultati. – Matho

0

è necessario spostare la funzionalità in xf in servizio/fabbrica separati. Quindi iniettarlo nel controller. Ciò rende abbastanza facile deriderlo durante i test.

0

Prova questa nel controller

var xf = this.xf = []; 

e questo nel tuo test

it ('checkEmail', function(){ 
var xf = $controller('MyCtrl', { $scope: $scope }).xf; 
spyOn(xf, 'validateUsername').and.callThrough(); 
xf.validateUsername(); 
}); 

Ma si dovrebbe capire che questo espone l'oggetto xf sul controller come accennato nel commento di Claies.

1

La variabile xf non è accessibile dall'esterno dell'ambito del controller (cioè non accessibile nei file di test dell'unità).

Devi aver fatto la cosa seguente:

angular 
    .module('myModule') 
    .controller(function ($scope) { 
    var xf = []; 
    // etc. 
    }); 

è possibile collegare la variabile xf all'istanza MyController volta angolare un'istanza esso:

angular 
    .module('myModule') 
    .controller(function ($scope) { 
    this.xf = []; 
    // etc. 
    }); 

Ma questo non è davvero un modo pulito di facendolo.Un modo migliore (a mio parere) sarebbe quello di creare una fabbrica:

angular 
    .module('myModule') 
    .factory('xfService', function() { 
    var xf = []; 

    function validateUsername(text) { 
     // etc. 
    } 

    function get() { 
     return xf; 
    } 

    return { 
     get: get, 
     validateUsername: validateUsername 
    }; 
    }); 

Ora, è possibile iniettare la fabbrica nel controller da utilizzare xf:

angular 
    .module('myModule') 
    .controller(function ($scope, xfService) { 
    // somewhere 
    var isValid = xfService.validateEmail($scope.email, '256'); 
    // to get the values in the array 
    var values = xfService.get(); 
    }); 

Infine, per i test di unità, diventa davvero facile testare il metodo validateEmail.

describe('Unit tests - xfService', function() { 
    var xfService; 
    beforeEach(angular.module('myModule')); 
    beforeEach(angular.inject(function (_xfService_) { 
     xfService = _xfService_; 
    }); 
    }); 

    describe('xfService.validateUsername', function() { 
    it('should return a boolean value', function() { 
     // for example 
     expect(typeof xfService.validateUsername('test')).toBe('boolean'); 
    }); 
    // add more unit tests to check that the method works as expected 
    }); 
}); 

Avrai bisogno di aggiungere il file angular-mocks alla configurazione Karma.

Grazie a Paul Podlech e Claies per i suggerimenti nei commenti/risposte.

Problemi correlati