这取决于你如何使用单例以及该单例是否实现了一个接口.如果它是一个单例的事实是一个实现细节,那么这可能没关系.如果您在要测试的代码中使用其单例性质,则更多的是问题.
以我的Noda Time项目为例.它有一个IClock界面代表"获取当前时间的方式".这有一个叫做SystemClocksingleton的实现.现在考虑使用它的一些代码:
public class BadClass
{
public bool IsIt2016Yet()
{
var now = SystemClock.Instance.Now;
return now.InUtc().Year >= 2016;
}
}
Run Code Online (Sandbox Code Playgroud)
我们无法在不改变SystemClock.Instance它的情况下测试该代码.该代码与单例类紧密耦合.但是,考虑一下:
public class GoodClass
{
private readonly IClock clock;
public GoodClass(IClock clock)
{
this.clock = clock;
}
public bool IsIt2016Yet()
{
var now = clock.Now;
return now.InUtc().Year >= 2016;
}
}
Run Code Online (Sandbox Code Playgroud)
现在你很好 - 在你的生产代码中你设置依赖注入以便SystemClock.Instance在任何你想要的地方使用IClock,但在测试代码中你可以使用假时钟 - 比如NodaTime.Testing包中提供的那个.在生产中,代码最终将使用单例,但它并没有与它紧密耦合.
当然,假设您已经适当地设置了依赖注入.如果你想在任何地方构建一个实例而不关心它需要一个时钟的事实,你可以选择一个选项,它可以选择将类连接到SystemClock单例:
public GoodClass(IClock clock)
{
this.clock = clock;
}
public GoodClass() : this(SystemClock.Instance)
{
}
Run Code Online (Sandbox Code Playgroud)
现在它仍然是可测试的(并且通常是灵活的)因为你可以传入时钟,但它很方便,因为它有效地"默认"到系统时钟.(您可以使用可选参数执行此操作,并null使用最终SystemClock.Instance作为另一种选择的参数.)
| 归档时间: |
|
| 查看次数: |
134 次 |
| 最近记录: |