Почему дату и время нельзя сравнивать?

Мой модульный тест C# имеет следующее утверждение:

Assert.AreEqual(logoutTime, log.First().Timestamp);

Почему это не удалось со следующей информацией:

Assert.AreEqual failed. Expected:<4/28/2010 2:30:37 PM>. Actual:<4/28/2010 2:30:37 PM>.

Разве они не одинаковы?

Обновить:

Используйте это, если вам нужно только второе:

Assert.AreEqual(logoutTime.ToString(), log.First().Timestamp.ToString());

9 ответов

Решение

Вы убедились, что число тиков / миллисекунд одинаково?

Если вы делаете DateTime.Now() дважды за спиной они будут казаться одинаковыми с точностью до минуты и, возможно, даже с точностью до секунды, но они часто будут варьироваться в зависимости от тиков. Если вы хотите проверить равенство только с точностью до минуты, сравните каждый DateTime только до этой степени. Для получения информации о округлении DateTimes, смотрите здесь


Примечание о разрешении:

Свойство Now часто используется для измерения производительности. Однако из-за низкого разрешения он не подходит для использования в качестве инструмента сравнения. Лучшая альтернатива - использовать класс Секундомер.

Попробуйте что-то вроде Assert.AreEqual(logoutTime.Ticks, log.First().Timestamp.Ticks)

Метод сбоя Assert, вероятно, вызывает ToString() для DateTime, который возвращает усеченную, удобочитаемую форму даты без компонента в миллисекундах. Вот почему кажется, что они равны, когда, на самом деле, объект DateTime имеет точность в 100 наносекунд (известный как отметка). Это означает, что крайне маловероятно, что два объекта DateTime будут иметь одинаковое значение. Для сравнения вы, вероятно, хотите усечь значение, возможно, отформатировав дату в соответствии с требуемой точностью.

Используя Entity Framework, если вы выбираете из базы данных, используя .AsNoTracking() DateTime свойство будет округлено очень немного, тогда как оно не обязательно будет округлено без .AsNoTracking() если оригинальное значение все еще находится в памяти. Таким образом, для интеграционных тестов, включающих обратную передачу в базу данных, я думаю, что лучше всего использовать .ToString() потому что база данных немного снизит точность.

Работая над модульным тестом, я обнаружил, что приведенные ниже шаги очень полезны, чтобы сравнить некоторую дату с фиктивной датой.

Поле фиктивной даты, как показано ниже:

      mockDate = new DateTime(2020, 10, 10)

Вызов метода обслуживания.

Утверждение можно сделать так:

      Assert.AreEqual("10/10/2020 12:00:00 AM", _service.startDate.ToString());

Примечание : при выполнении утверждения

  • Мы должны указать дату, например: 10/10/2020 12:00:00 AM
  • Затем в элементе даты метода службы нам нужно применить ToString(), это преобразует дату и время в строковое значение для сравнения.

Вы уверены, что logoutTime и log.First().Timestamp оба введены как DateTime?

Если это так, они могут также иметь разные значения для более конкретной временной информации (например, миллисекунды).

Предполагая, что logoutTime и log.First().Timestamp имеют тип DateTime, вы должны попробовать использовать вместо этого:

Assert.AreEqual(logoutTime.Ticks, log.First().Timestamp.Ticks);

С 2018 года XUnit поддерживает сравнение DateTime с заданной точностью:

      Assert.Equal(DateTime.Now, myObject.CreatedAt, TimeSpan.FromSeconds(1));

Я полагаю Assert.AreEqual<T> использования Object.Equals() определить равенство объектов, но не значений.

Вероятно, это утверждение сравнивает два разных объекта и поэтому возвращает false.

Другие вопросы по тегам