2009-06-25 7 views
6

Est-ce que quelqu'un a une bonne approche pour tester ses UserTypes? Par exemple, j'ai un objet dans mon modèle appelé DateRange, qui a un début DatePoint et une fin DatePoint. En plus de rendre les opérations de type plage disponibles pour deux DateTimes, ces objets me permettent d'ajuster la précision de la tâche en cours (par exemple, Jour, Heure, Minute, etc.). Lorsque stocké sur la base de données pour une application sur laquelle je travaille, j'ai juste besoin de stocker le début et la fin comme DateTime, pas de nulls autorisés. Je ne peux pas penser à la façon de mapper ce sans UserType, j'ai donc:Tests unitaires NHibernate UserTypes

/// <summary>User type to deal with <see cref="DateRange"/> persistence for time sheet tracking.</summary> 
public class TimePeriodType : IUserType 
{ 

    public SqlType[] SqlTypes { 
     get { 
      var types = new SqlType[2]; 
      types[0] = new SqlType(DbType.DateTime); 
      types[1] = new SqlType(DbType.DateTime); 
      return types; 

     } 
    } 

    public Type ReturnedType 
    { 
     get { return typeof(DateRange); } 
    } 

    /// <summary>Just return <see cref="DateRange.Equals(object)"/></summary> 
    public new bool Equals(object x, object y) 
    { 
     return x != null && x.Equals(y); 
    } 

    /// <summary>Just return <see cref="DateRange.GetHashCode"/></summary> 
    public int GetHashCode(object x) 
    { 
     return x.GetHashCode(); 
    } 

    public object NullSafeGet(IDataReader rs, string[] names, object owner) 
    { 
     var start = (DateTime)NHibernateUtil.DateTime.NullSafeGet(rs, names[0]); 
     var end = (DateTime)NHibernateUtil.DateTime.NullSafeGet(rs, names[1]); 

     return new DateRange(start, end, TimeSlice.Minute); 
    } 

    public void NullSafeSet(IDbCommand cmd, object value, int index) { 
     Check.RequireNotNull<DateRange>(value); 
     Check.RequireArgType<DateRange>(value); 
     var dateRange = ((DateRange)value); 

     NHibernateUtil.DateTime.NullSafeSet(cmd, dateRange.Start, index); 
     NHibernateUtil.DateTime.NullSafeSet(cmd, dateRange.End, index); 
    } 

    public object DeepCopy(object value) { 
     Check.RequireNotNull<DateRange>(value); 
     Check.RequireArgType<DateRange>(value); 
     var dateRange = ((DateRange) value); 

     return new DateRange(dateRange.Start, dateRange.End); 
    } 

    public bool IsMutable 
    { 
     get { return false; } 
    } 

    public object Replace(object original, object target, object owner) { 
     //because it is immutable so we can just return it as is 
     return original; 
    } 

    public object Assemble(object cached, object owner) { 
     //Used for caching, as it is immutable we can just return it as is 
     return cached; 
    } 

    public object Disassemble(object value) { 
     //Used for caching, as it is immutable we can just return it as is 
     return value; 
    } 
} 

}

Maintenant, je suis à la recherche d'un moyen de prouver qu'il fonctionne. Merci d'avance!

Cheers, Berryl

Répondre

8

J'ai créé un type d'utilisateur pour System.Drawing.Color, et voici comment je l'unité testé avec MSTest et Moq.

ColorUserType.cs:

 
public class ColorUserType : IUserType 
{ 
    public object Assemble(object cached, object owner) 
    { 
     return cached; 
    } 

    public object DeepCopy(object value) 
    { 
     return value; 
    } 

    public object Disassemble(object value) 
    { 
     return value; 
    } 

    public new bool Equals(object x, object y) 
    { 
     if(ReferenceEquals(x, y)) 
     { 
      return true; 
     } 
     if(x == null || y == null) 
     { 
      return false; 
     } 
     return x.Equals(y); 
    } 

    public int GetHashCode(object x) 
    { 
     return x == null ? typeof(Color).GetHashCode() + 473 : x.GetHashCode(); 
    } 

    public bool IsMutable 
    { 
     get 
     { 
      return true; 
     } 
    } 

    public object NullSafeGet(IDataReader rs, string[] names, object owner) 
    { 
     var obj = NHibernateUtil.String.NullSafeGet(rs, names[0]); 
     if(obj == null) 
     { 
      return null; 
     } 
     return ColorTranslator.FromHtml((string)obj); 
    } 

    public void NullSafeSet(IDbCommand cmd, object value, int index) 
    { 
     if(value == null) 
     { 
      ((IDataParameter)cmd.Parameters[index]).Value = DBNull.Value; 
     } 
     else 
     { 
      ((IDataParameter)cmd.Parameters[index]).Value = ColorTranslator.ToHtml((Color)value); 
     } 
    } 

    public object Replace(object original, object target, object owner) 
    { 
     return original; 
    } 

    public Type ReturnedType 
    { 
     get 
     { 
      return typeof(Color); 
     } 
    } 

    public SqlType[] SqlTypes 
    { 
     get 
     { 
      return new[] { new SqlType(DbType.StringFixedLength) }; 
     } 
    } 
} 

ColorUserTypeTests.cs

 
    [TestClass] 
    public class ColorUserTypeTests 
    { 
     public TestContext TestContext { get; set; } 

     [TestMethod] 
     public void AssembleTest() 
     { 
      var color = Color.Azure; 
      var userType = new ColorUserType(); 
      var val = userType.Assemble(color, null); 
      Assert.AreEqual(color, val); 
     } 

     [TestMethod] 
     public void DeepCopyTest() 
     { 
      var color = Color.Azure; 
      var userType = new ColorUserType(); 
      var val = userType.DeepCopy(color); 
      Assert.AreEqual(color, val); 
     } 

     [TestMethod] 
     public void DissasembleTest() 
     { 
      var color = Color.Azure; 
      var userType = new ColorUserType(); 
      var val = userType.Disassemble(color); 
      Assert.AreEqual(color, val); 
     } 

     [TestMethod] 
     public void EqualsTest() 
     { 
      var color1 = Color.Azure; 
      var color2 = Color.Bisque; 
      var color3 = Color.Azure; 
      var userType = new ColorUserType(); 

      var obj1 = (object)color1; 
      var obj2 = obj1; 

      Assert.IsFalse(userType.Equals(color1, color2)); 
      Assert.IsTrue(userType.Equals(color1, color1)); 
      Assert.IsTrue(userType.Equals(color1, color3)); 
      Assert.IsFalse(userType.Equals(color1, null)); 
      Assert.IsFalse(userType.Equals(null, color1)); 
      Assert.IsTrue(userType.Equals(null, null)); 
      Assert.IsTrue(userType.Equals(obj1, obj2)); 
     } 

     [TestMethod] 
     public void GetHashCodeTest() 
     { 
      var color = Color.Azure; 
      var userType = new ColorUserType(); 

      Assert.AreEqual(color.GetHashCode(), userType.GetHashCode(color)); 
      Assert.AreEqual(typeof(Color).GetHashCode() + 473, userType.GetHashCode(null)); 
     } 

     [TestMethod] 
     public void IsMutableTest() 
     { 
      var userType = new ColorUserType(); 
      Assert.IsTrue(userType.IsMutable); 
     } 

     [TestMethod] 
     public void NullSafeGetTest() 
     { 
      var dataReaderMock = new Mock(); 
      dataReaderMock.Setup(m => m.GetOrdinal("white")).Returns(0); 
      dataReaderMock.Setup(m => m.IsDBNull(0)).Returns(false); 
      dataReaderMock.Setup(m => m[0]).Returns("#ffffff"); 

      var userType = new ColorUserType(); 
      var val = (Color)userType.NullSafeGet(dataReaderMock.Object, new[] { "white" }, null); 

      Assert.AreEqual("ffffffff", val.Name, "The wrong color was returned."); 

      dataReaderMock.Setup(m => m.IsDBNull(It.IsAny())).Returns(true); 
      Assert.IsNull(userType.NullSafeGet(dataReaderMock.Object, new[] { "black" }, null), "The color was not null."); 

      dataReaderMock.VerifyAll(); 
     } 

     [TestMethod] 
     public void NullSafeSetTest() 
     { 
      const string color = "#ffffff"; 
      const int index = 0; 

      var mockFactory = new MockFactory(MockBehavior.Default); 

      var parameterMock = mockFactory.Create(); 
      parameterMock.SetupProperty(p => p.Value, string.Empty); 

      var parameterCollectionMock = mockFactory.Create(); 
      parameterCollectionMock.Setup(m => m[0]).Returns(parameterMock.Object); 

      var commandMock = mockFactory.Create(); 
      commandMock.Setup(m => m.Parameters).Returns(parameterCollectionMock.Object); 

      var userType = new ColorUserType(); 

      userType.NullSafeSet(commandMock.Object, ColorTranslator.FromHtml(color), index); 
      Assert.AreEqual(0, string.Compare((string)((IDataParameter)commandMock.Object.Parameters[0]).Value, color, true)); 

      userType.NullSafeSet(commandMock.Object, null, index); 
      Assert.AreEqual(DBNull.Value, ((IDataParameter)commandMock.Object.Parameters[0]).Value); 

      mockFactory.VerifyAll(); 
     } 

     [TestMethod] 
     public void ReplaceTest() 
     { 
      var color = Color.Azure; 
      var userType = new ColorUserType(); 
      Assert.AreEqual(color, userType.Replace(color, null, null)); 
     } 

     [TestMethod] 
     public void ReturnedTypeTest() 
     { 
      var userType = new ColorUserType(); 
      Assert.AreEqual(typeof(Color), userType.ReturnedType); 
     } 

     [TestMethod] 
     public void SqlTypesTest() 
     { 
      var userType = new ColorUserType(); 
      Assert.AreEqual(1, userType.SqlTypes.Length); 
      Assert.AreEqual(new SqlType(DbType.StringFixedLength), userType.SqlTypes[0]); 
     } 
    } 
0

Je pensais que je pouvais railler/faux quelques-unes des dépendances, mais liquidées décider de la meilleure façon de le faire est à l'aide d'une base de données.

Certaines choses que j'ai appris le long du chemin:

1), il vaut la peine de l'effort lors de l'apprentissage des techniques NHibernate d'avoir un ensemble dédié d'outils, y compris un moyen de configurer rapidement db et dispositif d'essai pour elle (les mêmes types des outils agiles dont vous aurez besoin pour tout le reste, vraiment) et un laboratoire de test dédié dans lequel vous n'avez aucun investissement émotionnel.

2) les mocks ne se prêtent pas aux interfaces que vous ne possédez pas, comme IDataReader .

Vive