Подтвердить что ты не робот

Издевательские даты в тестах AngularJS/Jasmine

У меня есть директива, которая несколько раз инициализирует объект 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);
});

Для unittesting самой директивы, которая вызывает ageInYears и несколько других подобных функций, это не будет работать, поскольку я после одного вызова Date() stubDateConstructor будет иметь reset Date() для реального объекта Date.

Есть ли собственный способ в AngularJS/Jasmine для обработки этих ситуаций, или я должен смотреть в Sinon, например.

4b9b3361

Ответ 1

Жасмин (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);
});

Ответ 2

Простое решение заключалось бы в создании службы Angular Dates, которая предоставляет объекты Date для вас - у нее может быть даже просто один метод - Dates.now() -, который просто отправляет обратно текущую дату, возвращая new Date(). Затем вы используете эту услугу, когда что-то должно получить текущую дату.

Затем это позволяет вам вводить другую службу Dates при модульном тестировании, например, такую, которая всегда возвращает определенную дату по вашему выбору при вызове, а не текущее время.

Ответ 3

angular.mock.TzDate будет лучшей альтернативой. это приходит как помощник из angular mocks и по-настоящему безопасно защищает ваш тест из системного часового пояса или любых других зависимостей

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

это хорошо работает с Жасмином или моккой

Ответ 4

Я смог издеваться, используя комбинацию тайных поддельных таймеров, чтобы высмеять таймеры окна и angular сервисный интервал для angular для распознавания изменений времени. Здесь проверка countDownService использует внутренне как службу javscript Date, так и angular normal Что-то вроде:

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

Вы также захотите убедиться, что в свой файл karma.conf.js также включен sinon js sinon-timers-1.8.1.js.