【问题标题】:Assembly.GetEntryAssembly().CodeBase precludes unit testing [duplicate]Assembly.GetEntryAssembly().CodeBase 排除单元测试 [重复]
【发布时间】:2012-05-24 00:28:25
【问题描述】:

可能重复:
.NET NUnit test - Assembly.GetEntryAssembly() is null

我正在编写一个日志库。默认情况下,我希望库写入为应用程序命名的公共应用程序数据文件夹中的目录。例如,如果应用程序名为“MyApplication.exe”,我希望数据保存在“C:\ProgramData\MyApplication”中。

我正在使用这段代码来构建路径:

   private static string loggingDataPath = 
      Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) +
      Path.DirectorySeparatorChar + 
      Path.GetFileNameWithoutExtension(Assembly.GetEntryAssembly().CodeBase) +
      Path.DirectorySeparatorChar;

这完全符合预期,但有一个问题。我无法对库进行单元测试!

当我尝试运行单元测试时,它们都因 System.NullReferenceException 而失败。如果我用字符串替换“Assembly.GetEntryAssembly().CodeBase”调用,单元测试将再次正常运行。

我想我理解为什么会发生这种情况,但我不知道如何解决这个问题。我希望有人能够让我走上正义的道路。

TIA!

更新 (5-24-12):我不想对“loggingDataPath”的内容进行单元测试。仅存在“Assembly.GetEntryAssembly().CodeBase”调用会导致所有单元测试因上述异常而失败。请注意,“loggingDataPath”是静态的(因为它必须是静态库)。

【问题讨论】:

  • 在单元测试时你想要/期望什么日志路径?
  • @RJ Lohan:这不是那个问题的重复,它解决了调用结果的单元测试。我的问题是调用是静态的,因此在类初始化时运行。调用失败会导致库上的所有单元测试失败。
  • @erikH:我不在乎“loggingDataPath”包含什么值。我已经更新了问题以反映这一点。

标签: c# unit-testing


【解决方案1】:

不仅仅是单元测试会导致问题。

鉴于GetEntryAssembly() can return null when a managed assembly has been loaded from an unmanaged applicationCodeBase can contain a URL for assemblies downloaded from the Internet, and is not set for assemblies loaded from the GAC,我会避免将这种方法用于通用日志库。

如果这还不足以让您信服,其他问题是 (a) 非特权用户将没有对 CommonApplicationData 的写入权限,以及 (b) 您的应用程序的多个实例尝试写入同一个日志文件将是问题。

相反,我会在配置中定义日志文件的位置。

你建议我把它放在哪里来避免这个问题?

正如我所说,我会在配置中定义它(例如 app.config 中的 appSetting)。这是最灵活的。如果要将其放在 CommonApplicationData 下,可以使用在从配置文件中读取时使用 Environment.ExpandEnvironmentVariables 方法扩展的环境变量。例如:

<appSettings>
    <add key="logFile" value="%ALLUSERSPROFILE%\MyApp\MyLogFile.log" />
    ...
</appSettings>

您仍然需要解决授予非特权用户访问权限的问题,并避免从多个实例访问时发生争用。您说您的底层日志库支持并发访问,但请注意,这将产生潜在的性能成本,具体取决于您的日志记录的详细程度。

【讨论】:

  • 感谢您指出这些问题。
  • 这不是一个通用库,而是一个用于完全由我控制的特定解决方案的库。永远不会从非托管应用程序调用该库,也不会从“网络”下载程序集。
  • 非特权用户问题是个问题。我试图将数据放在使用计算机的每个人都可以访问它的地方(而不是按用户存储)。你会建议我把它放在哪里来避免这个问题?
  • 最后,这个库封装了另一个日志库(Raize CodeSite),它可以处理对日志文件的多个同时访问。
  • 有没有办法让我想要的路径(显然不是 CommonApplicationData)在库进行单元测试时可以正常运行?
【解决方案2】:

忽略先前答案的明智建议并仅解决我的问题,这是我解决问题的方法:

   public static string LoggingDataPath { 
      get { 
         return loggingDataPath.Length > 0 ? loggingDataPath : 
         Environment.GetFolderPath(Environment.SpecialFolder.CommonDocuments) + 
         Path.DirectorySeparatorChar + 
         Path.GetFileNameWithoutExtension(Assembly.GetEntryAssembly().CodeBase) + 
         Path.DirectorySeparatorChar; 
      } 

      set { loggingDataPath = value; } 
   } 

此解决方案避免在首次访问静态类时初始化“loggingDataPath”,从而避免调用“Assembly.GetEntryAssembly().CodeBase”。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-19
    • 2016-08-21
    • 1970-01-01
    • 1970-01-01
    • 2023-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多