面向客户的依赖注入 API

Dependency Injection on Customer Facing API

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

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

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

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 个构造函数:一个用于注入依赖项的单元测试,另一个用于生产,它以其他方式创建依赖项,可能调用另一个 ctor。查找 "poor-man's DI":

class MyClass
{
    public MyClass(IService service)
    { 
        this.Service = service;
    }

    public MyClass() : this(new Service())
    {
    }
}

我用"Property Injection"解决了这个问题。

"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.
        }
    }

感谢大家的帮助。