有没有人有一个很好的方法来测试他们的UserTypes?
举例来说,我的模型中有一个名为DateRange的对象,它有一个DatePoint start和DatePoint结束。除了为两个DateTime提供范围类型操作之外,这些对象还允许我调整手头任务的精度(即日,小时,分钟等)。当存储到我正在处理的应用程序的数据库时,我只需要将开始和结束存储为DateTime,不允许空值。我想不出如何在没有UserType的情况下映射它,所以我有:
/// <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;
}
}
}
现在我正在寻找一种证明它有效的方法。提前谢谢!
干杯, Berryl
答案 0 :(得分:9)
我为System.Drawing.Color创建了一个用户类型,这是我用MSTest和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] ); } }
答案 1 :(得分:0)
我原本以为我可以在这里模拟/伪造一些依赖项,但最终确定最佳方法是使用数据库。
我一路上学到了一些东西:
1)学习NHibernate技术以获得一套专用工具(包括快速配置数据库和测试夹具的方法)时,值得付出努力(实际上,你需要的其他所有类型的敏捷工具)还有一个专门的测试实验室,你没有情感投资。
2)模拟不适合你不拥有的接口,比如IDataReader。
干杯