使用Log组件时,我们通常自定义ILogger接口,使用Log4Net等组件进行适配来定义不同的实现类。使用Log4Net日志组件时,为了即方便单元测试又能使用配置文件,我们通过Log4Net的ILogger接口使用Log4Net,对Log4Net进行单元测试时我们可以通过使用MemoryAppender方式测试。

1.定义ILogger接口

ILogger可以通过使用日志级别的枚举类型精简方法数量,也可以不适用枚举直接定义多个方法。

  1. public interface ILogger
  2. {
  3. void Debug(string format, params string[] args);
  4.  
  5. void Error(string format, params string[] args);
  6.  
  7. void Fatal(string format, params string[] args);
  8.  
  9. void Info(string format, params string[] args);
  10.  
  11. void Warn(string format, params string[] args);
  12. }

2.创建使用Log4Net适配的实现类Log4NetAdapter

  1. public class Log4NetAdapter : ILogger
  2. {
  3. private readonly ILog _rootLogger;
  4.  
  5. public Log4NetAdapter(ILog rootLogger)
  6. {
  7. this._rootLogger = rootLogger;
  8. }
  9.  
  10. public void Debug(string format, params string[] args)
  11. {
  12. if (this._rootLogger.IsDebugEnabled)
  13. {
  14. _rootLogger.Debug(string.Format(format, args));
  15. }
  16. }
  17.  
  18. public void Info(string format, params string[] args)
  19. {
  20. if (this._rootLogger.IsInfoEnabled)
  21. {
  22. _rootLogger.Info(string.Format(format, args));
  23. }
  24. }
  25.  
  26. public void Warn(string format, params string[] args)
  27. {
  28. if (this._rootLogger.IsWarnEnabled)
  29. {
  30. _rootLogger.Warn(string.Format(format, args));
  31. }
  32. }
  33.  
  34. public void Error(string format, params string[] args)
  35. {
  36. if (this._rootLogger.IsErrorEnabled)
  37. {
  38. _rootLogger.Error(string.Format(format, args));
  39. }
  40. }
  41.  
  42. public void Fatal(string format, params string[] args)
  43. {
  44. if (this._rootLogger.IsFatalEnabled)
  45. {
  46. _rootLogger.Fatal(string.Format(format, args));
  47. }
  48. }
  49. }

3.使用MemoryAppender进行单元测试

  1. public class Log4netAdapterTest
  2. {
  3. private MemoryAppender _appender;
  4.  
  5. [Fact]
  6. public void Test()
  7. {
  8. _appender = new MemoryAppender
  9. {
  10. Name = "Unit Testing Appender",
  11. Layout = new log4net.Layout.PatternLayout("%message")
  12. };
  13. _appender.ActivateOptions();
  14.  
  15. var root = ((Hierarchy)log4net.LogManager.GetRepository()).Root;
  16. root.AddAppender(_appender);
  17. root.Repository.Configured = true;
  18.  
  19. ILogger logger = new Log4NetAdapter(log4net.LogManager.GetLogger("root"));
  20. logger.Info("test {0}", "message");
  21. Assert.Equal(_appender.GetEvents()[].MessageObject.ToString(), string.Format("test {0}", "message"));
  22. }
  23. }

4.创建Log4NetLoggerFactory

通常我们使用配置文件方式配置Log4Net,因此创建Log4NetLoggerFactory提供从配置文件中创建的ILog对象。

  1. public class LoggerFactory
  2. {
  3. private static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(LoggerFactory));
  4.  
  5. static LoggerFactory()
  6. {
  7. log4net.Config.XmlConfigurator.Configure();
  8. }
  9.  
  10. public static ILogger GetLogger()
  11. {
  12. return new Log4NetAdapter(log);
  13. }
  14. }

参考的配置文件

  1. <configSections>
  2. <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
  3. </configSections>
  4.  
  5. <log4net>
  6. <root>
  7. <level value="ALL" />
  8. <appender-ref ref="RollingLogFileAppender" />
  9. </root>
  10. <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
  11. <param name="File" value="App_Data/Logs/log.txt" />
  12. <param name="AppendToFile" value="true" />
  13. <param name="RollingStyle" value="Date" />
  14. <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
  15. <preserveLogFileNameExtension value="true" />
  16. <datePattern value="yyyyMMdd" />
  17. <param name="StaticLogFileName" value="false" />
  18. <layout type="log4net.Layout.PatternLayout">
  19. <conversionPattern value="%date [%thread] %-5level %logger [%ndc] - %message%newline" />
  20. </layout>
  21. </appender>
  22. </log4net>

运行结果:

4.通过依赖注入使用ILogger

在ASP.NET项目中使用时,通过DI容器进行注入。

  1. protected void Application_Start()
  2. {
  3. //...
  4. ObjectFactory.AddSingleton<ILogger, Log4NetAdapter>(LoggerFactory.GetLogger());
  5. //...
  6. }

ASP.NET 系列:单元测试之Log4Net的更多相关文章

  1. 补习系列(8)-springboot 单元测试之道

    目录 目标 一.About 单元测试 二.About Junit 三.SpringBoot-单元测试 项目依赖 测试样例 四.Mock测试 五.最后 目标 了解 单元测试的背景 了解如何 利用 spr ...

  2. ASP.NET Core搭建多层网站架构【3-xUnit单元测试之简单方法测试】

    2020/01/28, ASP.NET Core 3.1, VS2019, xUnit 2.4.0 摘要:基于ASP.NET Core 3.1 WebApi搭建后端多层网站架构[3-xUnit单元测试 ...

  3. ASP.NET Core搭建多层网站架构【12-xUnit单元测试之集成测试】

    2020/02/01, ASP.NET Core 3.1, VS2019, xunit 2.4.1, Microsoft.AspNetCore.TestHost 3.1.1 摘要:基于ASP.NET ...

  4. ASP.NET 系列:单元测试

    单元测试可以有效的可以在编码.设计.调试到重构等多方面显著提升我们的工作效率和质量.github上可供参考和学习的各种开源项目众多,NopCommerce.Orchard等以及微软的asp.net m ...

  5. 使用VisualStudio进行单元测试之二

    借着工作忙的借口,偷了两天懒,今天继续单元测试之旅.前面说了如何进行一个最简单的单元测试,这次呢就跟大家一起来熟悉一下,在visual studio中如何进行数据驱动的单元测试. 开始之前先来明确一下 ...

  6. iOS 单元测试之XCTest详解(一)

    iOS 单元测试之XCTest详解(一) http://blog.csdn.net/hello_hwc/article/details/46671053 原创blog,转载请注明出处 blog.csd ...

  7. 玩转单元测试之Testing Spring MVC Controllers

    玩转单元测试之 Testing Spring MVC Controllers 转载注明出处:http://www.cnblogs.com/wade-xu/p/4311657.html The Spri ...

  8. 玩转单元测试之WireMock -- Web服务模拟器

    玩转单元测试之WireMock -- Web服务模拟器 WireMock 是一个灵活的库用于 Web 服务测试,和其他测试工具不同的是,WireMock 创建一个实际的 HTTP服务器来运行你的 We ...

  9. 单元测试之NSNull 检测

    本文主要讲 单元测试之NSNull 检测,在现实开发中,我们最烦的往往就是服务端返回的数据中隐藏着NSNull的数据,一般我们的做法是通过[data isKindOfClass:[NSNull cla ...

随机推荐

  1. Linux磁盘管理之创建磁盘分区05

    一.磁盘基础知识 磁盘安装在计算机上后,在系统读取到硬盘后并不能直接使用,必须经过分区.格式化才能够正确使用.这一次主要是针对磁盘分区进行简单总结,存储设备类型:U盘.光盘.软盘.硬盘.磁带. 硬盘接 ...

  2. hdu 3472 HS BDC(混合路的欧拉路径)

    这题是混合路的欧拉路径问题. 1.判断图的连通性,若不连通,无解. 2.给无向边任意定向,计算每个结点入度和出度之差deg[i].deg[i]为奇数的结点个数只能是0个或2个,否则肯定无解. 3.(若 ...

  3. [引] Security tips for web developers

    Source :Security tips for web developers

  4. Linux软件安装-yum安装

    虽然RPM包安装软件很方便.快捷,但是还是需要现有安装包才能安装.为了更为方便的安装软件,发展出了利用网络自动安装的方式--yum安装. 使用yum安装的前提是机器可以上网. 1.配置yum源 在/e ...

  5. JavaWeb学习----Cookie实现记住密码的功能

    [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...

  6. WPF捕获未处理的异常

     WPF程序中,对于异常的捕获一般使用try/catch块.就像程序中的bug一样,很难保证程序中所有的异常都能够通过try/catch捕获.如果异常没有被捕获,轻则影响用户体验,严重时会导致数据丢失 ...

  7. monkeyrunner之eclipse中运行monkeyrunner脚本之环境搭建(四)

    monkeyrunner脚本使用Python语法编写,但它实际上是通过Jython来解释执行. Jython是Python的Java实现,它将Python代码解释成Java虚拟机上的字节码并执行,这种 ...

  8. [转]SQL 操作结果集 -并集、差集、交集、结果集排序

    本文转自:http://www.cnblogs.com/kissdodog/archive/2013/06/24/3152743.html 操作结果集 为了配合测试,特地建了两个表,并且添加了一些测试 ...

  9. [每日菜单]lunch menu for Wednesday, February 24 2016

    HIGHLIGHTS ​** Boiled Broccoli原味西兰花  ​ Steamed Turbot with Chili剁椒蒸多宝鱼  ​* Rye Bread黑麦面包  CHINESE CU ...

  10. 关于反射blog

    非常好的Java反射例子   疯狂java   在学习编程的过程中,我觉得不止要获得课本的知识,更多的是通过学习技术知识提高解决问题的能力,这样我们才能走在最前方,更多Java学习,请浏览疯狂java ...