2013-06-13 20 views
27

Ho una direttiva che inizializza l'oggetto Date più volte in diverse funzioni. Quando Unità testare le singole funzioni posso gestire spegnendo la data così:Date di derisione nei test AngularJS/Jasmine

(function (global) { 
    var NativeDate = global.Date; 

    global.stubDateConstructor = function (fakeDate) { 
     global.Date = function() { 
      global.Date = NativeDate; 
      return fakeDate; 
     } 
    } 
}(this)); 

// ageInYears() 
it("should return the age in years of the person given his/her birthdate", function() { 
    stubDateConstructor(new Date('2010/01/01')); 
    expect(ageInYears('01-01-1990')).toBe(20); 
    stubDateConstructor(new Date('2010/01/01')); 
    expect(ageInYears('01-01-1900')).toBe(110); 
}); 

Per unit testing della direttiva stessa, che chiama l'ageInYears e diverse altre funzioni simili questo non sta andando a lavorare come ho dopo una chiamata alla data() stubDateConstructor avrà resettato Data() all'oggetto Data reale.

C'è un modo nativo in AngularJS/Jasmine per gestire queste situazioni, o dovrei cercare in Sinon, ad esempio?

+0

è albeggiare su di me, ora che potrei avere per inizializzare la data una volta e passare quella alle funzioni che la richiedono .. forse questa è la soluzione migliore? – Maarten

+0

Sono un fan di Timecop.js me stesso. Qualsiasi libreria con funzioni come Timecop.travel e Timecop.freeze ottiene la mia approvazione. – ivarni

+0

sembra che sinon.js possa anche fornire il time-mocking che si applica alle date (dipende dal supporto del browser) http://sinonjs.org/docs/#clock – ossek

risposta

50

Jasmine (2.2) L'orologio può prendere in giro date e ora.

http://jasmine.github.io/2.2/introduction.html#section-Mocking_the_Date

Per esempio (dalla documentazione):

it("mocks the Date object and sets it to a given time", function() { 
    var baseTime = new Date(2013, 9, 23); 
    jasmine.clock().mockDate(baseTime); 

    jasmine.clock().tick(50); 
    expect(new Date().getTime()).toEqual(baseTime.getTime() + 50); 
}); 
+0

grazie, sembra che non esistesse quando ho chiesto ma sembra lo strumento giusto ora – Maarten

12

Una soluzione semplice sarebbe quella di creare un servizio di Dates angolare che fornisce Date oggetti per voi - potrebbe anche solo avere un unico metodo - Dates.now() - che proprio restituisce la data corrente restituendo new Date(). Quindi si utilizza questo servizio ogni volta che qualcosa deve ottenere la data corrente.

Questo quindi consente di iniettare un altro servizio Dates durante il test dell'unità, ad esempio uno che restituisce sempre una data specifica di propria scelta al momento della chiamata, anziché l'ora corrente.

+0

Così semplice, la mia mente si aggirava per tutti i tipi di stupidi scenari eccessivamente complessi . Grazie fratello! – rooftop

0

Sono stato in grado di prendere in giro usando una combinazione di sinon's fake timers per prendere in giro i timer della finestra e l'angolare mock interval service per il riconoscimento angolare delle modifiche di orario. Qui, il countDownService in prova si avvale internamente sia javscript Date e di angolare normale interval service Qualcosa di simile:

describe('when start time was 3000 milliseconds and 1001 milliseconds have passed', function() { 
    var startTime; 
    var elapse; 
    beforeEach(function(){ 
     this.clock = sinon.useFakeTimers(); 
     startTime = 3000; 
     elapse = 1001; 
    }); 

    var elapseMillis = function(intervalMock,sinonClock,millis){ 
     sinonClock.tick(millis); 
     intervalMock.flush(millis); 
    }; 

    it('elapsedMillis + timeRemainingMillis should == startime', 
     inject(function($rootScope,$interval,countdownService) { 
     countdownService.startTimer(startTime); 
     elapseMillis($interval,this.clock,elapse); 
     //jasmine clock does not mock Date 
     //see https://github.com/pivotal/jasmine/issues/361 
     var elapsedMillis = countdownService.getElapsedMillis(); 
     var timeRemainingMillis = countdownService.getTimeRemainingMillis(); 
     expect(elapsedMillis + timeRemainingMillis).toEqual(startTime); 
     expect(elapsedMillis).toEqual(elapse); 
    })); 

    afterEach(function(){ 
     this.clock.restore(); 
     startTime = 0; 
     elapse = 0; 
    }); 
    }); 

Ti consigliamo di fare in modo di includere e js Sinon di sinon-timers-1.8.1.js nei tuoi karma.conf.js file di proprietà, anche .

1

angular.mock.TzDate farebbe una migliore nativo alternativa qui. questo si presenta come un aiuto da schernisce angolari e guardia veramente al sicuro la tua prova dal fuso orario di sistema o qualsiasi altre dipendenze

https://docs.angularjs.org/api/ngMock/type/angular.mock.TzDate

questo gioca bene con il gelsomino o moka

Problemi correlati