【问题标题】:NLog and Unit TestingNLog 和单元测试
【发布时间】:2016-09-13 18:39:40
【问题描述】:

我正在为我的记录器使用 NLog。当我运行 .exe 或什至通过 Visual Studio 进行调试时,一切正常,NLog 仍将写入文件。

但是,如果我运行一个通过单元测试调用记录器的对象,则该文件已创建但它是空的。是否需要在配置中添加额外的设置/规则才能让 NLog 写入单元测试下的文件?

我可以为此模拟 NLog 而没有日志转储,但我想看看在我决定只模拟 NLog 之前是否可以让它工作。尽管这仅发生在单元测试中并且可以正常工作,但这是我的日志配置和代码。我省略了文件名。

public static void Info(string app, string m)  => EngineLogger.Logger.Info($"{app} : {m}");



<targets>
    <target name="infoFile"
            xsi:type="File"
            layout="${date:format=yyyy-MM-dd HH\:mm\:ss} ${pad:padding=5:inner=${level:uppercase=true}} ${logger} ${message}"
            fileName="leftoutForQuestion"
            keepFileOpen="false"
            encoding="iso-8859-2" />
    <target name="errorFile"
            xsi:type="File"
            layout="${date:format=yyyy-MM-dd HH\:mm\:ss} ${pad:padding=5:inner=${level:uppercase=true}} ${logger} ${message}"
            fileName="leftOutForQuestion"
            keepFileOpen="false"
            encoding="iso-8859-2" />
  </targets>
  <rules>
    <logger name="*" minlevel="Debug" maxlevel="Info" writeTo="infoFile" />
    <logger name="*" minlevel="Warn" maxlevel="Fatal" writeTo="errorFile" />
  </rules>

这是来自内部日志的错误:

Error Error has been raised. Exception: System.Runtime.InteropServices.COMException (0x800700A1): The specified path is invalid. (Exception from HRESULT: 0x800700A1)
   at System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo)
   at NLog.Internal.FileAppenders.BaseFileAppender.WindowsCreateFile(String fileName, Boolean allowFileSharedWriting)
   at NLog.Internal.FileAppenders.BaseFileAppender.TryCreateFileStream(Boolean allowFileSharedWriting)
   at NLog.Internal.FileAppenders.BaseFileAppender.CreateFileStream(Boolean allowFileSharedWriting)
   at NLog.Internal.FileAppenders.RetryingMultiProcessFileAppender.Write(Byte[] bytes)
   at NLog.Targets.FileTarget.WriteToFile(String fileName, LogEventInfo logEvent, Byte[] bytes, Boolean justData)
   at NLog.Targets.FileTarget.ProcessLogEvent(LogEventInfo logEvent, String fileName, Byte[] bytesToWrite)
   at NLog.Targets.FileTarget.Write(LogEventInfo logEvent)
   at NLog.Targets.Target.Write(AsyncLogEventInfo logEvent)

【问题讨论】:

  • 你检查过 nlog 的内部日志文件是否有错误吗?还发现这个链接可能是同样的问题:stackoverflow.com/questions/1672998/nlog-with-vs-2008-unit-test
  • 我也试过了,但同样的问题仍然存在。使用正确的文件名创建文件,但文件为空。 D=
  • 你为什么登录到文件目标而不是内存目标?
  • 因为它有效?我不确定该定位如何导致它仅在单元测试下中断?同样,如果我只是运行一个 exe,那么日志记录会遇到零问题。除非我在这里遗漏了什么......谢谢

标签: c# visual-studio unit-testing nlog


【解决方案1】:

我发现所有配置都位于单元测试项目的 app.config 中,而不是 NLog.Config 文件。请务必声明配置部分,然后声明 NLog 配置。下面是我的示例 app.config

    <configuration>
      <configSections>

         <section name="nlog"
                    type="NLog.Config.ConfigSectionHandler, NLog"/>
  </configSections>
  <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

    <targets>


      <target name="file" xsi:type="File"
             layout="${longdate} ${logger} ${message}"
             fileName="${basedir}/logs/${shortdate}.log" />

    </targets>
   <rules>
       <logger name="*" minlevel="Trace" writeTo="file"/>

    </rules>

  </nlog>
</configuration>

【讨论】:

    【解决方案2】:

    当并行执行单元测试时,最好为每个并行执行使用隔离的 NLog LogFactory:

    LogFactory logFactory = new LogFactory();
    logFactory.Configuration = new XmlLoggingConfiguration(configFilePath, true, logFactory); 
    Logger logger = logFactory.GetCurrentClassLogger();
    

    另见https://github.com/NLog/NLog/wiki/Configure-component-logging

    如果您需要从字符串而不是文件加载 NLog 配置:

    string currentDir = System.IO.Directory.GetCurrentDirectory();
    System.IO.StringReader sr = new System.IO.StringReader(xmlString);
    System.Xml.XmlReader xr = System.Xml.XmlReader.Create(sr);
    logFactory.Configuration.Configuration = new NLog.Config.XmlLoggingConfiguration(xr, currentDir);
    

    另见https://github.com/NLog/NLog/wiki/Explicit-NLog-configuration-loading

    【讨论】:

      【解决方案3】:

      不确定这是否是问题,但可以肯定:

      从单元测试环境中读取 NLog.config 可能很困难,因此在单元测试中从字符串中读取配置会更加健壮。我们使用助手:

          protected XmlLoggingConfiguration CreateConfigurationFromString(string configXml)
          {
              XmlDocument doc = new XmlDocument();
              doc.LoadXml(configXml);
      
              return new XmlLoggingConfiguration(doc.DocumentElement, Environment.CurrentDirectory);
          }
      

      然后:

       LogManager.Configuration = CreateConfigurationFromString(@"
                  <nlog throwExceptions='true'>
                      <targets><target name='debug' type='debug' layout='${message}' /></targets>
                      <rules>
                          <logger name='*' minlevel='info' appendto='debug'>
                              <filters>
                                  <whencontains layout='${message}' substring='msg' action='ignore' />
                              </filters>
                          </logger>
                      </rules>
                  </nlog>");
      

      不要忘记在每次测试之前或之后重置LogManager.Configuration

      更新:在配置中启用 throwExceptions。

      还有关于错误。您可能需要在单元测试中使用绝对路径。

      【讨论】:

      • 非常感谢您的回复!我会试一试,让你知道。 =) 再次感谢
      • 我试过这个解决方案,但同样的问题仍然发生。感谢您的意见 =) 非常感谢
      • 您是否尝试过在 nlog 中打开调试并查看内部 nlog 文件中是否记录了任何内容?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-06
      相关资源
      最近更新 更多