我们正在使用内部简单的Logger类来处理应用程序的日志记录任务(.NET 3.5)。
记录器代码非常陈旧,设计与此类似:
public class Logger : ILogger
{
private ILogger instance;
private static ILogger Instance
{
// Initialized on first use.
get { return instance; }
}
public static void Debug(string msg)
{
instance.Debug(msg);
}
public static void Error(string msg)
{
....
}
}
实例本身在第一次使用时被初始化(懒惰)。
根据其严格的“书本”实现,这不是Singleton,但是,从所有调用代码访问此类是 静态访问 。
出于测试目的和其他架构原因,我希望能够用其他内容替换内部实例(注入它)。
我怎样才能轻松实现这一目标?我们目前没有使用任何IoC容器,但我不想将一个setter暴露给Instance属性,因为这会破坏整个Singleton之类的设计。
有关如何为此提出解决方案的任何建议吗?
答案 0 :(得分:2)
考虑使用Fakes Framework进行测试。你可以使用类似这样的东西将调用存根到静态方法
ShimLogger.Instance = () => new LoggerMock();
对于.net 3.5,您可以使用Moles Framework来存根静态方法调用。配置代码如下所示:
MLogger.Instance = () => new LoggerMock();
需要将静态方法Instance
设为public,但在此配置之后,每次调用static方法都将返回您的模拟实例。
答案 1 :(得分:1)
事实上,制定者并不是一个好的选择。
相反,我会考虑两种可能的方法。首先,explcit配置方法:
public class Logger : ILogger {
public void ConfigureLogger( ILogger logger ) {
this.instance = logger;
}
}
这种方法的一个优点是意图明确,而且你必须以明确的方式调用这种方法。
另一种选择是允许你在配置中传递一种记录器:
<appSettings>
<add key="loggerType" value="The.Type.From, Some.Assembly" />
</appSettings>
然后,在您的Logger
类中重写初始化例程,以便在配置参数存在时,您更喜欢配置中提供的类型OVER默认类型。
这种方法的一个优点是您可以使用配置更改重新配置客户端,而无需更改代码。
无论如何,IoC容器不会咬人。介绍一个,因为它可以长期获得回报。
答案 2 :(得分:0)
我不会自己动手。我使用企业库几乎满足了我的所有日志记录需求。它适用于桌面和asp.net项目。 Asp.net可能会有点问题,因为你必须处理服务器上的安全性,但我已经完成了。
人们也喜欢Log4Net,但我从未使用它,因此我无法评论它。
答案 3 :(得分:0)
我会使用Logger修改代码。而不是通过Logger.Instance访问记录器,而是将所需的记录器实例传递给对象。然后在您的工厂和/或组合根中,将Logger.Instance作为生产代码中记录器的来源传递,在单元测试中,可以很容易地使用模拟记录器。
public class Foo
{
private readonly ILogger logger;
public Foo(ILogger logger)
{
if (logger == null)
throw new ArgumentNullException("logger");
this.logger = logger;
}
public void Func()
{
try
{
// do something
}
catch (Exception ex)
{
// call the provided logger dependency
this.logger.WriteError(ex);
// not the static singleton property
Logger.Instance.WriteError(ex);
}
}
}
答案 4 :(得分:0)
另一个想法是为internal
属性设置Instance
setter,并使用InternalsVisibleTo属性使内部setter对测试程序集可见。请注意,如果包含记录器的程序集名称较强,则必须在PublicKey
属性中指定InternalsVisibleTo
。显然,这是最有帮助的(在不让其他开发人员意外地 - 或故意 - 将Instance设置为其他东西的意义上)如果您的记录器所在的是自己的程序集或某种基础结构程序集,其中大多数开发/日志记录未发生