面向客户的依赖注入 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.
}
}
感谢大家的帮助。
我目前正在设计一个 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.
}
}
感谢大家的帮助。