단위 테스트 nhibernate userTypes
-
20-08-2019 - |
문제
누구든지 사용자 유형을 테스트하는 데 좋은 접근 방식이 있습니까?
예를 들어, DateRange라는 모델에 Daterange라는 객체가 있습니다. 여기에는 DatePoint 시작 및 DatePoint End가 있습니다. 두 개의 데이터 시간 동안 범위 유형 작업을 사용할 수있을뿐만 아니라 이러한 객체를 사용하면 당면한 작업의 정밀도 (즉, 하루, 시간, 분 등)를 조정할 수 있습니다. 작업중 인 응용 프로그램에 대해 DB에 저장되면 시작과 종료를 DateTime으로 저장하면 널이 허용되지 않습니다. 사용자 유형없이 이것을 매핑하는 방법을 생각할 수 없으므로 다음과 같습니다.
/// <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;
}
}
}
이제 나는 그것이 효과가 있다는 것을 증명할 방법을 찾고 있습니다. 미리 감사드립니다!
건배, 베리
해결책
System.Drawing.Color 용 사용자 유형을 만들었고 여기에 MSTEST와 함께 테스트 한 방법은 다음과 같습니다. 모크.
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) Nhibernate 기술을 배우는 데 도움이 될만한 가치가 있습니다. DB 및 테스트 고정물 (실제로 다른 모든 것에 필요한 동일한 애자일 도구) 및 전용 전용 도구를 포함하여 전용 도구 세트를 갖도록 노력할 가치가 있습니다. 감정적 인 투자가없는 테스트 랩.
2) 모의는 Idatareader와 같이 소유하지 않는 인터페이스에 스스로를 빌려주지 않습니다.
건배