2013-06-13 118 views
27

我有一個指令可以在多個函數中多次初始化Date對象。 當單元測試的各個功能我可以處理磕碰這樣的日期:在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); 
}); 

對於單元測試指令本身,它調用ageInYears和其他一些類似的功能,這不會一個電話後,我的工作到Date()stubDateConstructor將重置Date()爲真正的Date對象。

在AngularJS/Jasmine中是否有一種本地方式來處理這些情況,還是我應該看看Sinon?

+0

它的曙光在我身上,我可能有初始化日期並將其傳遞給需要它的函數。可能這是最好的解決方案嗎? – Maarten

+0

我是Timecop.js自己的粉絲。任何具有Timecop.travel和Timecop.freeze功能的庫都會得到我的批准。 – ivarni

+0

它看起來像sinon.js也可能提供適用於日期的時間模擬(取決於瀏覽器的支持)http://sinonjs.org/docs/#clock – ossek

回答

50

茉莉花(2.2)時鐘可以模擬日期和時間。

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

例如(從文檔):

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

謝謝,看起來它不存在,當我問,但現在似乎是正確的工具 – Maarten

12

一個簡單的解決方案是創建一個角度Dates服務,提供Date對象爲你 - 它甚至可能只是一個單一的方法 - Dates.now() - 只是通過返回new Date()發回的當前日期。只要需要獲取當前日期,您就可以使用此服務。

然後,您可以在單元測試時注入不同的Dates服務,例如在調用時總是返回您選擇的特定日期而不是當前時間的服務。

+0

這麼簡單,我的思想徘徊到各種愚蠢的過度複雜的情況。多謝兄弟! – rooftop

0

我能夠模擬使用sinon's fake timers的組合來模擬窗口的計時器和角度的mock interval service角度識別時間變化。在這裏,被測countDownService使得內部同時使用javscript Date和角度的正常interval service喜歡的東西的:

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

你會希望確保,包括興農JS的sinon-timers-1.8.1.js在karma.conf.js文件屬性,也。