2009-04-18 80 views
2

我有一些基本的類與克隆方法:單位在C#中測試的克隆方法與起訂量

public class SimpleClass 
{ 
    public int ValueA { get; set; } 

    public string ValueB { get; set; } 

    public ulong ValueC { get; set; } 

    public SimpleClass TypedClone() 
    { 
     var item = new SimpleClass 
     { 
      ValueA = this.ValueA, 
      ValueB = this.ValueB, 
      ValueC = this.ValueC 
     }; 

     return item; 
    } 
} 

我想一個單元測試,會告訴我,如果我加重視,但忘記將它添加到克隆方法。我的第一個嘗試是使用Moq和它的VerifyGet方法來確保每個屬性都被訪問。

public void GenericCloneTest() 
    { 
     var mock = new Mock<SimpleClass>(); 
     var c = mock.Object.GenericClone(); 
     var properties = typeof(SimpleClass).GetProperties(); 

     foreach (var property in properties) 
     { 
      var expression = Expression.Property(
       Expression.Parameter(typeof(SimpleClass), "c"), 
       property); 

      var type = Expression.GetFuncType(typeof (SimpleClass), 
       property.PropertyType); 

      var actionExpression = Expression.Lambda(type, expression, 
       Expression.Parameter(typeof(SimpleClass), "c")); 

      mock.VerifyGet<object> 
       ((Expression<Func<SimpleClass,object>>)actionExpression); 
     } 
    } 

這並不工作,因爲VerifyGet方法需要知道屬性訪問的返回類型,我想不出任何方式在運行時將其插入(你會發現我的跛腳企圖使用撞擊和燃燒的「物體」)。

我甚至不確定使用Moq是一個好主意,它只是我的第一個。

更新:由於沒有快速簡單的通用方法來測試克隆方法,我決定爲每個類編寫特定於類型的測試。這仍然讓我知道何時添加屬性的問題。我決定把它添加到我的克隆單元測試中:

 var signature = typeof (Connection) 
      .GetProperties() 
      .Select(p => p.Name) 
      .Aggregate(
       new StringBuilder(), 
       (builder, name) => 
        builder.Append(name)).ToString(); 

     Assert.AreEqual(
      "DataSessionStateDataTechnologyBytesReceivedBytesSentDuration", 
      signature); 

如果我添加屬性,則測試將失敗。當簽名匹配失敗時,它仍然依賴於我有足夠的責任來解決測試的其餘部分。

回答

1

確保您獲得所有字段的最簡單方法之一是簡單地使用MemberwiseClone()方法。這將自動將所有類字段複製到新實例。

+0

謝謝保羅!我一直認爲必須有這樣的.NET內置的東西,但還沒有找到。這在我想做出快速淺拷貝的任何地方都很有用。 – MichaC 2009-04-18 02:37:01

2

你不想在這裏使用Moq,你只需要使用一些反射。基本上寫一個測試,創建一個對象的實例,設置每個屬性,克隆它,然後確保每個屬性在克隆上相同。

就像Paul說的那樣,檢查出MemberwiseClone(),它基本上是爲你做的,或者至少實現ICloneable,這是一個標準的做法。 (MemberwiseClone()只做一個淺拷貝,這就是爲什麼你可能需要實現ICloneable)。然後你甚至可以編寫一個測試,通過你的程序集查看所有實現ICloneable並測試它的東西。

+0

我開始只用反射來思考它,但最難的部分就是「設置每個屬性」的步驟。我必須將每個屬性設置爲默認值以外的其他值來驗證克隆方法,但是我擁有包含任意數量類型的屬性集合。我必須編寫知道如何更改和比較可能遇到的任何類型的代碼。問題是,這是否比爲每種類型編寫獨特的克隆測試更有效。 – MichaC 2009-04-18 02:48:48