2014-01-09 37 views
3

我正在創建將需要比較相同類型成員的兩個對象的單元測試。我決定使用SemanticComparison庫來處理此任務,而無需編寫自定義比較器代碼。它在比較平面對象時非常有效,當對象包含也需要比較成員的嵌套對象時會出現問題。使用SemanticComparison比較嵌套的對象屬性

public class Outer 
{ 
    public string Name { get; set; } 
    public Inner Inner { get; set; } 
} 

public class Inner 
{ 
    public string Name { get; set; } 
    public string Value { get; set; } 
} 

public class Service 
{ 
    public Outer Method() 
    { 
     return new Outer() 
     { 
      Name = "outerName", 
      Inner = new Inner() 
      { 
       Name = "innerName", 
       Value = "value1" 
      } 
     }; 
    } 
} 

這不會起作用,因爲內部對象是通過引用進行比較,而不是按成員:

[Test] 
    public void SimpleTest1() 
    { 

     // setup 
     var expectedLikeness = new Outer() 
     { 
      Name = "outerName", 
      Inner = new Inner() 
      { 
       Name = "innerName", 
       Value = "value1" 
      } 
     }.AsSource().OfLikeness<Outer>(); 

     var sut = new Service(); 
     // exercise sut 
     var actual = sut.Method(); 
     // verify 
     expectedLikeness.ShouldEqual(actual); 
    } 

爲了使它工作,我不得不創建嵌套對象的代理,以使其覆蓋默認等於實施。

[Test] 
    public void SimpleTest2() 
    { 

     // setup 
     var expectedLikeness = new Outer() 
     { 
      Name = "outerName", 
      Inner = new Inner() 
      { 
       Name = "innerName", 
       Value = "value1" 
      }.AsSource().OfLikeness<Inner>().CreateProxy() 
     }.AsSource().OfLikeness<Outer>(); 

     var sut = new Service(); 
     // exercise sut 
     var actual = sut.Method(); 
     // verify 
     expectedLikeness.ShouldEqual(actual); 
    } 

好,它工作正常,但試想,經過一些服務代碼重構我們引入,使內部類的值屬性是與預期值不同的bug。 SemanticComparison的一個很酷的功能是它可以記錄導致不平等的成員的名字。但是,在這種情況下,它只會返回「Inner」作爲不匹配,而不是Inner類中特定屬性的名稱。

我錯過了什麼嗎?是否可以將其配置爲能夠返回實際不匹配的成員。

對於本例中的簡單數據結構來說,這顯然不是問題,但它可能是測試真實生活代碼的不便之處。

回答

3

由於沒有人回答,我會提供我自己的答案。

所以,看來你不能這樣做OOTB,除非你寫一些額外的代碼。 我已經將代碼包裝在一組擴展方法中。這些方法可以讓你指定哪些內部屬性/集合屬性應該使用內部相似性進行比較,而不是通過引用。您不需要手動創建任何代理,所有內容均由這些擴展內部處理。所有內部比較的結果都會被記錄下來,因此您可以準確查看哪個成員具有無效值。

以下是使用「WithInnerLikeness」擴展方法的問題的測試。

[Test] 
    public void ServiceTest3() 
    { 
     // setup 
     var expected = new Outer() 
     { 
      Name = "outerName", 
      Inner = new Inner() 
      { 
       Name = "innerName", 
       Value = "value2" 
      } 
     }; 

     var expectedLikeness = expected.AsSource().OfLikeness<Outer>() 
      .WithInnerLikeness(d => d.Inner, s => s.Inner) 
      ; 

     var sut = new Service(); 
     // exercise sut 
     var actual = sut.Method(); 
     // verify 
     expectedLikeness.ShouldEqual(actual); 
    } 

你可以看到內部的對象不匹配的值的屬性,所以這個測試應該失敗。並且在輸出中出現以下消息:

Comparing inner properties using likeness. Source: s => s.Inner Destination: d => d.Inner. 
The source and destination values are not equal. Details: The provided value ClassLibrary1.Inner did not match the expected value ClassLibrary1.Inner. The following members did not match: 
- Value. 

Ploeh.SemanticComparison.LikenessException : The provided value ClassLibrary1.Outer did not match the expected value ClassLibrary1.Outer. The following members did not match: 
- Inner. 

您可以在github上找到源代碼和更多示例。

https://github.com/jmansar/SemanticComparisonExtensions

+0

難道是很容易能夠做出某種自動內/自動代理相似的?我有深度和廣泛的嵌套數據結構,我想與構造的測試數據或數據庫/序列化往返結果進行比較。即'expected.AsSource().Likeness ().WithAutoLikeness()。ShouldEqual(actual).' – Holstebroe

+0

我認爲,當我創建這些擴展。但是,據我所知,沒有對原始圖書館進行修改是不可能的,需要一些思考。 – JMansar

+0

對不起,但這不適用於.NET標準:( – SuperJMN