2008-12-12 10 views
6

Przy użyciu NUnit 2.2 na .NET 3.5, następujący test kończy się niepowodzeniem, gdy używana jest funkcja DateTime.Equals. Czemu?Dlaczego ten test jednostki kończy się niepowodzeniem podczas testowania równości DateTime?

[TestFixture] 
public class AttributeValueModelTest 
{ 
    public class HasDate 
    { 
     public DateTime? DateValue 
     { 
      get 
      { 
       DateTime value; 
       return DateTime.TryParse(ObjectValue.ToString(), out value) ? value : new DateTime?(); 
      } 
     } 

     public object ObjectValue { get; set; } 
    } 

    [Test] 
    public void TwoDates() 
    { 
     DateTime actual = DateTime.Now; 
     var date = new HasDate {ObjectValue = actual}; 
     Assert.IsTrue(date.DateValue.Value.Equals(actual)); 
    } 
} 
+0

prostu ciekawy, żadnego powodu do przyklejania do NUnit 2.2 ?? 2.8 wydaje się być najnowszym – Perpetualcoder

+0

Nie staram się trzymać wersji 2.2. Jest tylko na moim komputerze, ponieważ przyszedł z TestDriven.NET, wraz z 2.4. czego mi brakuje? – flipdoubt

Odpowiedz

14

Daty nie są równe. TryParse upuszcza kilka kleszczy. Porównaj wartości Tick.

Dla jednego testu:

Console.WriteLine(date.DateValue.Value.Ticks); 
Console.WriteLine(actual.Ticks); 

Wynik:

633646934930000000 
633646934936763185 
+0

Trochę mi zajęło, ale wymyśliłem to po utworzeniu TimeSpan między tymi dwoma datami. +1 dla ciebie. – flipdoubt

+0

+1 do ciebie za myślenie i wiedząc, że !! – Perpetualcoder

0

ja nie wiem, czy to jest to samo w .NET, ale w Javie równości często będzie porównać tylko jeśli przypadki są takie same, jeśli wartości nie są takie same. Zamiast tego chciałbyś użyć compareTo.

+0

Nie, w Javie operator == służy do równości odniesienia, a metoda równości() służy do równości wartości. –

+0

@Adam: nie domyślnie. Musisz zastąpić metodę Object's equals, aby uzyskać opisywane zachowanie. –

+0

W Rosji Sowieckiej == równa się Object.Equals –

0
 

public DateTime? DateValue 
     { 
      get 
      { 
       DateTime value; 
       bool isDate = DateTime.TryParse(ObjectValue.ToString(), out value); 
       return isDate ? new DateTime?(value) : new DateTime?(); 
      } 
     } 
 
+0

Nie uruchomiłem kodu. jest to wyłącznie oparte na spojrzeniu. Przepraszam, jeśli nie pomogę. – shahkalpesh

+0

Niestety, ale to jest TryParse, to jest problem. – flipdoubt

+0

Dzięki. Kiedy spojrzałem na kod, wygląda na to, że zwraca DateTime (gdy TryParse się powiedzie) zamiast DateTime ?. Jedną z rzeczy, których się tutaj uczę, jest to, że możesz przypisać instancję DateTime do DateTime? :) – shahkalpesh

3

Problemem nie jest naprawdę TryParse, ale faktycznie toString().

Obiekt DateTime rozpoczyna się od precyzji (jeśli nie dokładności) aż do milionowej sekundy. ToString() konwertuje na ciąg znaków, z dokładnością tylko do sekundy.

TryParse robi wszystko, co może, dzięki podarunkom.

Jeśli dodasz specyfikator formatu (zgodnie z "yyyy-MM-dd HH:mm:ss.ffffff"), powinien działać.

+0

Hmmm, Object.ToString() nie pobiera specyfikatora formatu. Jakieś sugestie? – flipdoubt

1

Aby określić format zawierający dokładność, można użyć metody String.Format(). Przykład, że James daje wyglądałby następująco:

String.Format("{0:yyyy-MM-dd HH:mm:ss.ffffff}", ObjectValue); 

Nie wiem, co to będzie zrobić, gdy go przekazywać coś, co nie jest randka.

Być może prostszym sposobem jest dodanie szczególny przypadek, gdy już masz obiekt Date:

public DateTime? DateValue 
    { 
     get 
     { 
      DateTime value = ObjectValue as DateTime; 
      if (value != null) return value; 
      return DateTime.TryParse(ObjectValue.ToString(), out value) ? value : new DateTime?(); 
     } 
    } 
Powiązane problemy