2012-12-06 161 views
2

在我開始之前我的問題我想指出,我知道有堆棧溢出類似的問題噸。不幸的是,這些問題都沒有幫助我在具體情景中找到一個好的解決方案。包含邏輯的靜態工廠方法的單元測試

問題:

我想要寫包含邏輯靜態工廠方法一個單元測試。我正在尋找一種方法來單元測試這種方法,即使它是靜態的。如果這是不可能的,也許有人可以爲我的班級指出一個更好的設計。我也考慮過使用IoC,但是考慮到單元測試並沒有看到優勢。

的代碼:

public class Db 
{ 
    private XmlMapping mapping; 

    public static Db<T> Create() 
    { 
     var mapping = XmlMapping.Create(typeOf(T).Name); 
     return new Db(mapping); 
    } 

    private Db(XmlMapping mapping) 
    { 
     this.mapping = mapping; 
    } 
} 

public class XmlMapping //class under test 
{ 
    public static XmlMapping Create(string filename) //method under test 
    {    
     try 
     { 
      ValidateFilename(filename); 
      //deserialize xml to object of type XmlMapping 
      var result = Deserialize(filename); 
      if (result.IsInValid()) 
       throw Exception() 
      return result; 
     } 
     catch (Exception) 
     { 
      throw new DbException(); 
     } 
    } 
} 

方法創建我想單元測試是類XmlMapping內。此方法序列化一個xml文件並生成一個XmlMapping類型的對象。我試圖爲序列化部分寫一個存根。但不想在構造函數中使用Mapping類調用我的數據庫工廠(構造函數注入)。

編輯:

我的數據庫工廠是通用的。通用型是用來找出哪些XML文件應louded即: - (!THX傑夫)的typeof(T)=客戶> XmlMapping-FILE = Customer.xml

解決方案:

public class XmlMapping : IMapping //class under test 
{ 
    internal static Func<Type, IMapping> DeserializeHandler { get; set; } 

    static XmlMapping() 
    { 
     DeserializeHandler = DeserializeMappingFor; 
    } 

    public static IMapping Create(Type type) 
    { 
     try 
     { 
      var mapping = DeserializeHandler(type); 
      if (!mapping.IsValid()) 
       throw new InvalidMappingException(); 
      return mapping; 
     } 
     catch (Exception ex) 
     { 
      throw new DataException("Failed to load mapping configuration from xml file.", ex); 
     } 
    } 

    internal XmlMapping(IMapping mapping) 
    { 
     this.Query = mapping.Query; 
     this.Table = mapping.Table; 
     this.Entity = mapping.Entity; 
     this.PropertyFieldCollection = mapping.PropertyFieldCollection; 
    } 

    private XmlMapping() { } 
} 


[TestClass] 
public class MappingTests //testing class 
{ 
    [TestMethod] 
    public void Create_ValidDeserialization_ReturnsObjectInstance() 
    { 
     XmlMapping.DeserializeHandler = MakeFakeHandlerFor(MakeMappingStub()); 
     var result = XmlMapping.Create(typeof(ActivityDto)); 
     Assert.IsInstanceOfType(result, typeof(XmlMapping)); 
    } 
} 
+0

如何溝通XmlMapping類您想要反序列化的Xml文件? –

+0

啊我忘了那部分......我會編輯我的問題 – MUG4N

+0

所以,你試圖用適當的參數來驗證「反序列化」是否被調用? –

回答

1

我會使用假動作處理程序來協助驗證反序列化調用的內容。讓我們添加一個Func委託屬性,並將其默認爲您的序列化方法。您的XmlMapping類和測試會喜歡這樣的:

public class XmlMapping //class under test 
{ 

    static XmlMapping() 
    { 
     // Default the handler to the normal call to Deserialize 
     DeserializeHandler = Deserialize; 
    } 

    public static XmlMapping Create(string filename) //method under test 
    { 
     //deserialize xml to object of type XmlMapping 
     //preudocode: 
     var result = DeserializeHandler(string.Format("{0}.xml",filename)); 
     //... 
     return result; 
    } 

    // Abstract indirection function to allow you to swap out Deserialize implementations 
    internal static Func<string, XmlMapping> DeserializeHandler { get; set; } 

    private static XmlMapping Deserialize(string fileName) 
    { 
     return new XmlMapping(); 
    } 

} 

public class CreateTests { 

    public void CallingDeserializeProperly() 
    { 

     // Arrange 
     var called = false; 
     Func<string, XmlMapping> fakeHandler = (string f) => 
     { 
      called = true; // do your test of the input and put your result here 
      return new XmlMapping(); 
     }; 

     // Act 
     XmlMapping.DeserializeHandler = fakeHandler; 
     var m = XmlMapping.Create("test"); 

     // Assert 
     Assert.IsTrue(called); 

    } 

} 
+0

嘿,傑夫,這看起來很有趣!我明天會試一試。感謝您的努力。我很感激。 – MUG4N

+1

傑夫這是我見過這個問題的最佳解決方案。很好的回答! – MUG4N

+1

嘰嘰喳喳我,如果你有單位測試幫助的任何進一步的需求 - 我是twitter @csharpfritz –