重构构造函数中的代码或存根/填充它?

时间:2013-05-31 17:11:27

标签: c# unit-testing microsoft-fakes

我有一个我正在测试的方法。此方法的构造函数调用其基类构造函数,然后在其基类构造函数中设置一些成员,然后执行一个方法从数据库中获取数据,然后将一些数据库值设置为更多成员(所有这些都在构造函数中完成) )。

我应该为了测试我的原始方法,在构造函数中删除对数据库的调用并重构它以便它只设置一些成员,然后我可以在我的测试中轻松运行构造函数并删除任何接口。传入(在这种情况下为1)或者我应该尝试在构造数据库调用的构造函数中填充方法吗?

    // method under test
    public override DateTime ResolveDate(ISeries comparisonSeries, DateTime targetDate)
    {
        switch (comparisonSeries.Key)
        {
            case SeriesKey.SomeKey1:
            case SeriesKey.SomeKey2:
            case SeriesKey.SomeKey3:
            case SeriesKey.SomeKey4:
            case SeriesKey.SomeKey5:
                return DateHelper.PreviousOrCurrentQuarterEnd(targetDate);
            default:
                break;
        }

        return base.ResolveDate(comparisonSeries, targetDate);
    }
// constructor
    public ReportForm(SeriesKey key, IAppCache cache)
        : base(key, cache)
    {
        //sets some base members here.
    }

 // base class that the constructor calls
 public abstract class SeriesBase : ISeries
{
    #region variables

    protected IAppCache clientCache;
    // other members below

        // base constructor
public SeriesBase(SeriesKey key, IAppCache cache)
    {
        this.key = key;
        this.clientCache = cache;
        this.infoPack = new SeriesInfo();
        this.InitalizeSeries();
    }
private void InitalizeSeries()
    {
        Dictionary<string, object> qInfoSQL = new Dictionary<string, object>();
        qInfoSQL.Add("@SeriesID", this.key.ToIntString());

        DBServiceResult result = this.clientCache.DBService.FetchFromDB("spSeriesInit", CommandType.StoredProcedure, qInfoSQL);

        if (result.Failed)
            throw new NotImplementedException("whoat");

        this.SetPublishTimeLag(result.XMLResult.Elements("tbl0").FirstOrDefault());
        this.AddFormView(result.XMLResult.Elements("tbl1").FirstOrDefault());
        this.AddPresentation(result.XMLResult.Elements("tbl2").DefaultIfEmpty(null).FirstOrDefault());

        this.SetBridge();
        this.InitializeGenerics();

    }

this.clientCache.DBService.FetchFromDB(...)方法正在调用另一个调用方法FetchFromDB的接口DBService,这个fetchfromDb方法进入QSL服务器并检索数据集。

这是我的测试方法。

public void TestResolveDate()
    {
        //using (ShimsContext.Create())
        //{
        //    Stat.Pi.Data.Fakes.ShimAuthenticator
        //}

        var appCache = new Fakes.StubIAppCache();
        appCache.DBServiceGet = DbServiceGet;


        ReportFORM formReport = new ReportForm(SeriesKey.SomeKey1, appCache);

        var series = new Fr Fakes.StubISeries();

        DateTime date = formReport.ResolveDate(series, DateTime.Now);


        //Assert.
    }
private IDBService DbServiceGet()
    {
        Dictionary<string, object> dict = new Dictionary<string, object>();
        dict.Add("@SeriesID", "50");

        var service = new Fakes.StubIDBService();
        service.FetchFromUnicornStringCommandTypeDictionaryOfStringObject = (s, type, arg3) => dict 
        return service;

    }

1 个答案:

答案 0 :(得分:0)

1)正如Henk Holterman所说,构造函数不应该调用数据库。这既增加了耦合又降低了内聚力。

2)您可能正在寻找的设计模式称为工厂模式 - http://en.wikipedia.org/wiki/Factory_method_pattern - 这将建筑,初始化和人口分开。另一方面,您可能希望引入一个帮助器或处理程序类来处理对象的持久性方面。

3)放入数据库访问存根以执行测试是合理的,因为重构代码可能在您的管辖范围之外。但是,就个人而言,我建议引入一个持久性帮助程序类来将新创建的对象绑定到数据库值。