2008-12-12 8 views
6

En utilisant NUnit 2.2 sur .NET 3.5, le test suivant échoue lors de l'utilisation de DateTime.Equals. Pourquoi?Pourquoi ce test d'unité échoue-t-il lors du test de l'égalité 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

curiosité, aucune raison de coller à NUnit 2.2 ?? 2.8 semble être le dernier – Perpetualcoder

+0

Je ne fais pas un effort pour rester avec 2.2. C'est seulement sur ma machine car il est venu avec TestDriven.NET, avec 2.4. Qu'est-ce que je rate? – flipdoubt

Répondre

14

Les dates ne sont pas identiques. TryParse laisse tomber quelques ticks. Comparez les valeurs de Tick.

Pour un essai:

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

rendements:

633646934930000000 
633646934936763185 
+0

Il m'a fallu un peu, mais je l'ai compris après avoir créé un TimeSpan entre les deux dates. +1 pour vous – flipdoubt

+0

+1 à vous pour avoir pensé et savoir ça !! – Perpetualcoder

0

Je ne sais pas si cela est la même dans .NET, mais en Java les égaux sera souvent si les instances compare sont les mêmes, pas si les valeurs sont les mêmes. Au lieu de cela, vous souhaitez utiliser compareTo.

+0

Non, en Java, l'opérateur == est utilisé pour l'égalité de référence et la méthode equals() est utilisée pour l'égalité des valeurs. –

+0

@Adam: Pas par défaut. Vous devez remplacer la méthode equals de Object pour obtenir le comportement que vous décrivez. –

+0

En Russie soviétique, == égale 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

Je n'ai pas exécuté le code. c'est purement basé sur le regard. Je suis désolé, si je ne suis d'aucune aide. – shahkalpesh

+0

Désolé, mais c'est TryParse qui pose problème. – flipdoubt

+0

Merci. Lorsque j'ai regardé le code, il semble qu'il renvoie DateTime (lorsque TryParse a réussi) au lieu de DateTime ?. Une chose que j'apprends ici est que vous pouvez assigner une instance de DateTime à DateTime? :) – shahkalpesh

3

Le problème est pas vraiment TryParse, mais en fait ToString(). Un objet DateTime commence avec la précision (voire l'exactitude) jusqu'à la millionième de seconde. ToString() convertsit en une chaîne, avec précision seulement à une seconde.

TryParse fait de son mieux avec ce qui lui est donné.

Si vous ajoutez un spécificateur de format (le long des lignes "yyyy-MM-dd HH:mm:ss.ffffff"), cela devrait fonctionner.

+0

Hmmm, Object.ToString() ne prend pas de spécificateur de format. Aucune suggestion? – flipdoubt

1

Pour spécifier un format incluant toute la précision, vous pouvez utiliser la méthode String.Format(). L'exemple que James donne ressemblerait à ceci:

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

Je ne sais pas ce que cela va faire quand vous passez quelque chose qui est pas une date.

Peut-être une approche plus simple est d'ajouter un cas particulier lorsque vous avez déjà un objet 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?(); 
     } 
    } 
Questions connexes