对面向客户的API的依赖注入

时间:2018-08-01 19:27:19

标签: c# dependency-injection api-design

我目前正在设计一个API,但遇到了一个设计问题,我不确定该如何处理。

我有一个面向客户的课程,该课程依赖于模型中的另一个课程。我需要测试Customer Facing类,因为它包含业务逻辑。

通常,我会使用依赖注入来处理这种情况,就像这个人为的例子一样:

public interface IRunQuery
{
    ResultObject RunQuery();
}

public class CustomerFacing
{
    public CustomerFacing(IRunQuery needed)
    {
        Needed = needed;
    }

    IRunQuery Needed { get; }

    public void DoSomethingForCustomer()
    {
        // Do some stuff.
        result = Needed.RunQuery();
        // Do some more stuff.
    }
}

在单元测试时,我会插入IRunQuery接口的Stub;这是一个昂贵的操作。但是,这有一个巨大的问题。客户不了解IRunQuery。他们不需要了解它,CustomerFacing的构造函数应该是:

public CustomerFacing() { }

如何在不将依赖项注入构造函数中的情况下对CustomerFacing进行单元测试?

2 个答案:

答案 0 :(得分:1)

您可能有2个构造函数:一个用于在单元测试中注入依赖项,另一个用于生产,它以其他方式创建依赖项,可能会调用另一个ctor。查找“穷人的DI”:

payload

答案 1 :(得分:0)

我使用“属性注入”来解决此问题。

“ IRunQuery”具有非常合理的默认值。仅在测试用例中才需要对其进行修改。我可以将其定义为内部的,从而使它从消费者的视线中消失,同时仍然允许测试在对其进行访问之前对其进行修改。

    public interface IRunQuery
    {
        ResultObject RunQuery();
    }

    public class CustomerFacing
    {
        public CustomerFacing()
        {
        }

        private IRunQuery _needed = null;
        internal IRunQuery Needed
        {
            get
            {
                if (_needed = null)
                {
                    _needed = new StandardQuery();
                }

                return _needed;
            }
            set
            {
                _needed = value;
            }
        }

        public void DoSomethingForCustomer()
        {
            // Do some stuff.
            result = Needed.RunQuery();
            // Do some more stuff.
        }
    }

感谢大家的帮助。