37

いくつかの関数で Date オブジェクトを数回初期化するディレクティブがあります。個々の関数を単体テストするとき、次のように日付のスタブを処理できます。

(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 への 1 回の呼び出し後に Date() が実際の Date オブジェクトにリセットされるため、これは機能しません。

これらの状況を処理するための AngularJS / Jasmine のネイティブな方法はありますか、それとも Sinon を調べる必要がありますか?

4

4 に答える 4

12

簡単な解決策は、オブジェクトを提供する AngularDatesサービスを作成することです。メソッドが 1 つだけの場合もあります。メソッドを返すだけで、現在の日付が返されます。その後、何かが現在の日付を取得する必要があるときはいつでも、このサービスを使用します。DateDates.now()new Date()

Datesこれにより、単体テスト時に別のサービスを挿入できます。たとえば、呼び出されたときに現在の時刻ではなく、選択した特定の日付を常に返すサービスなどです。

于 2013-10-23T08:20:19.797 に答える
0

ウィンドウのタイマーをモックするためのsinon の偽のタイマーと、angularが時間の変化を認識するための angular のモック間隔サービスを組み合わせてモックすることができました。ここで、テスト対象の countDownService は、javascriptDateと angular の通常の間隔サービスの両方を内部的に使用します。

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

sinon jssinon-timers-1.8.1.jsも karma.conf.js ファイル プロパティに含めてください。

于 2014-02-04T16:12:05.947 に答える