如何在没有Moles或Isolator的情况下使用静态类进行单元测试的方法



我有一个方法

     public int GetHighestPriorityPriceRecordIndex(SearchAndExtractReply_2 priceInfoReply)
    {
        int index = 0;
        var priceExposableColumn = GetPriceColumn(priceInfoReply, "LPCIsPriceExposable");
        var pricingSourceIDColumn = GetPriceColumn(priceInfoReply, "LPCPricingSourceID");
        var priceExposablePriority = new Dictionary<string, int> { { "Y", 2 }, { "N", 1 } };
        var pricingSourcePriority = new Dictionary<string, int> { { "USA", 5 }, { "EME", 4 }, { "ASI", 3 }, { "DER", 2 }, { "NUS", 1 } };
        if (priceExposableColumn.Value != null)
            for (int i = 1; i < priceExposableColumn.Value.Length; i++)
                if (priceExposablePriority[priceExposableColumn.Value[i]] > priceExposablePriority[priceExposableColumn.Value[index]]
                    && pricingSourcePriority[pricingSourceIDColumn.Value[i]] > pricingSourcePriority[pricingSourceIDColumn.Value[index]])
                    index = i;
        return index;
    }
    private static StringColumn GetPriceColumn(SearchAndExtractReply_2 priceInfoReply, string columnName)
    {
        return (StringColumn)SearchAndExtractReply_2_Extension.GetColumn(priceInfoReply, columnName);
    }

我想对具有此方法的类进行单元测试,此方法使用静态类和方法SearchAndExtractReply_2_Extension.GetColumn。有什么更好的方法来重构这段代码,这样我就可以在没有Moles或Isolator的情况下测试这个方法了?或者更好地使用Moles来隔离代码?提前谢谢。

如果可以的话,进行重构。考虑到您仍然可以选择进行小代码更改,引入Moles听起来有点过头了。

关于重构。引入一个新的类,它的唯一职责是从SearchAndExtractReply_2对象中提取列。很简单:

public interface IColumnExtractor
{
    StringColumn GetPriceColumn(SearchAndExtractReply_2 source,
        string columnName);
}
public class ColumnExtractor : IColumnExtractor
{
    public StringColumn GetPriceColumn(SearchAndExtractReply_2 source, 
        string columnName)
    {
        return (StringColumn)SearchAndExtractReply_2_Extension.GetColumn(source, 
            columnName);
    }
}

现在,要么为原始方法提供这样的类实例(添加类型为IColumnExtractor的新参数),要么为整个类提供完全相同的提取器(例如,通过构造函数注入)。

public int GetHighestPriorityPriceRecordIndex(
    SearchAndExtractReply_2 priceInfoReply, IColumnExtractor columnExtractor)
{
    // use extractor object instead of static method
}

然后你可以使用任何免费的嘲讽框架(比如FakeItEasy或Moq)。

如果您依赖某个东西,则应该将其传递给方法。然后你的API就很清楚了,你可以从外面知道什么是需要的,什么是可以嘲笑的。这意味着您将构建逻辑和业务逻辑分开。当与Unity或Castle这样的依赖注入框架相结合时,它将在单元测试中为您提供良好的可测试代码和易于在生产中使用的代码。

我会为SearchAndExtractReply_2_Extension创建一个接口,然后将其作为参数传递给GetHighestPriorityPriceRecordIndex(如果在多个地方使用,也可能传递给构造函数)。然后,您可以模拟整个依赖关系,或者在进行集成测试时将"实际实现"传递给它。

最新更新