2009-06-25 19 views
6

Czy ktoś ma dobre podejście do jednostki testującej swoje UserTypes?Testowanie jednostek NHibernate UserTypes

Na przykład mam obiekt w moim modelu o nazwie DateRange, który ma początek DatePoint i koniec DatePoint. Oprócz wykonywania operacji typu zakresu dostępnych dla dwóch DateTimes, obiekty te pozwalają mi dostosować precyzję dla danego zadania (np. Day, Hour, Minute, itp.). Podczas przechowywania w bazie danych dla aplikacji, nad którą pracuję, wystarczy zapisać początek i koniec jako DateTime, bez dozwolonych zer. Nie mogę myśleć jak mapować to bez UserType, więc mam:

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

}

Teraz szukam sposobu, aby udowodnić, że działa. Z góry dziękuję!

Cheers, Berryl

Odpowiedz

8

I stworzył typ użytkownika dla System.Drawing.Color, a oto jak ja testowałem to jednostka z MSTest i 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

myślałem mógłbym szydzić/Fałszywy niektóre z zależnościami tutaj, ale likwidacji decydując najlepszy sposób, aby to zrobić to za pomocą bazy danych.

Niektóre rzeczy nauczyłem się po drodze:

1) jest to warte wysiłku podczas nauki technik NHibernate mieć dedykowany zestaw narzędzi, w tym sposób na szybką konfigurację db i oprzyrządowania dla niego (tego samego rodzaju zwinnych narzędzi, których będziesz potrzebować do wszystkiego, naprawdę) i dedykowanego laboratorium testowego, w które nie inwestujesz emocjonalnie.

2) makiety nie nadają się do interfejsów, które nie są Twoją własnością, np. IDataReader .

Cheers