簡體   English   中英

包含邏輯的靜態工廠方法的單元測試

[英]Unit Testing of a static factory method containing logic

在開始我的問題之前,我想指出的是,我知道在堆棧溢出中有很多類似的問題。 不幸的是,這些問題都沒有幫助我在具體情況下找到好的解決方案。

問題:

我想為包含邏輯的靜態工廠方法編寫單元測試。 我正在尋找一種對該方法進行單元測試的方法,即使它是靜態的。 如果這不可能,那么也許有人可以為我正在測試的班級指出更好的設計。 我也考慮過使用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();
        }
    }
}

我要進行單元測試的Create方法在XmlMapping類中。 此方法序列化xml文件並生成XmlMapping類型的對象。 我嘗試為序列化部分編寫存根。 但是不想用構造函數中的Mapping類調用我的數據庫工廠(構造函數注入)。

編輯:

我的數據庫工廠是通用的。 通用類型用於確定應該大聲顯示哪個xml文件,即: typeOf(T)= Customer-> 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));
    }
}

我將使用偽造的動作處理程序來幫助驗證反序列化調用的內容。 讓我們添加一個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);

    }

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM