我遇到了和你一样的问题——在我的例子中是使用 NLog 的静态方法:
LogManager.GetCurrentClassLogger()
我已将当前线程的主体替换为 Rhinomocks 存根:
var identity = MockRepository.GenerateStub<IIdentity>();
identity.Stub(x => x.IsAuthenticated).Return(true);
var principal = MockRepository.GenerateStub<IPrincipal>();
principal.Stub(x => x.Identity).Return(identity);
Thread.CurrentPrincipal = principal;
为我的代码运行单元测试引发了与原始问题相同的异常。
堆栈跟踪:
at System.AppDomain.get_Evidence()
at System.AppDomain.get_EvidenceNoDemand()
at System.AppDomain.get_Evidence()
at System.Configuration.ClientConfigPaths.GetEvidenceInfo(AppDomain appDomain, String exePath, String& typeName)
at System.Configuration.ClientConfigPaths.GetTypeAndHashSuffix(AppDomain appDomain, String exePath)
at System.Configuration.ClientConfigPaths..ctor(String exePath, Boolean includeUserConfig)
at System.Configuration.ClientConfigPaths.GetPaths(String exePath, Boolean includeUserConfig)
at System.Configuration.ClientConfigurationHost.RequireCompleteInit(IInternalConfigRecord record)
at System.Configuration.BaseConfigurationRecord.GetSectionRecursive(String configKey, Boolean getLkg, Boolean checkPermission, Boolean getRuntimeObject, Boolean requestIsHere, Object& result, Object& resultRuntimeObject)
at System.Configuration.BaseConfigurationRecord.GetSection(String configKey)
at System.Configuration.ClientConfigurationSystem.System.Configuration.Internal.IInternalConfigSystem.GetSection(String sectionName)
at System.Configuration.ConfigurationManager.GetSection(String sectionName)
at NLog.Config.XmlLoggingConfiguration.get_AppConfig()
at NLog.LogFactory.get_Configuration()
at NLog.LogFactory.GetLogger(LoggerCacheKey cacheKey)
at NLog.LogFactory.GetLogger(String name)
at NLog.LogManager.GetCurrentClassLogger()
at MyClassHere...
正如您从堆栈跟踪中看到的那样,尝试读取配置文件,但这是行不通的 - 为什么?因为现在模拟的当前主体不再是我们最初拥有的 WindowsPrincipal - 它现在是一个模拟主体,不会有任何类型的 Windows 文件访问权限。
想一想这里有几种方法可以解决这个问题。
- 将记录器注入到我的类中,这样它就可以被存根(我想我可能无论如何都应该这样做..)。这将允许我为 Thread 主体使用存根。
- 修改线程上现有的 WindowsPrincipal(或基于它创建另一个)以添加调用我的方法所需的角色。
-- 更新--
为了解决我的问题,最后我决定按照上面的第一个建议运行。为了避免编写我自己的 NLog Logger 抽象,我只是利用了 Common.Logging 提供的内容。类构造函数现在接受 ILog 作为其参数之一,注入记录器的 Unity 配置如下所示:
container.RegisterType<ILog>(new TransientLifetimeManager(), new InjectionFactory(x => LogManager.GetCurrentClassLogger()));
同时,我的单元测试现在允许我传入一个模拟记录器。
var logger = MockRepository.GenerateStub<ILog>();