如何使用静态类,没有Moles或Isolator的单元测试方法?

时间:2012-01-31 16:01:20

标签: c# unit-testing refactoring

我有一个方法

     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来隔离代码? 提前谢谢。

2 个答案:

答案 0 :(得分:2)

如果您依赖某些东西应该传递给该方法。然后你的API很清楚,你可以从外面告诉我们需要什么以及可以嘲笑什么。这意味着您将构造逻辑和业务逻辑分开。当与Unity或Castle等依赖注入框架结合使用时,它将为您提供单元测试中的可测试代码以及​​易于在生产中使用的代码。

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

答案 1 :(得分:2)

如果可以,请进行重构。考虑到你仍然可以选择改变小代码,让摩尔听起来有点过分。

关于那个重构。引入一个新类,其唯一责任是从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
}

然后你可以使用任何免费的模拟框架(例如FakeItEasyMoq)。