【问题标题】:How to debug nHibernate/RhinoMocks TypeInitializer exception如何调试 nHibernate/RhinoMocks TypeInitializer 异常
【发布时间】:2016-01-12 22:33:24
【问题描述】:

拔出我的头发试图调试这个。今天早上早些时候,这段代码运行良好,但我看不出我为破坏它所做的更改。现在,每当我尝试打开 nHibernate 会话时,都会收到以下错误:

测试方法 BCMS.Tests.Repositories.BlogBlogRepositoryTests.can_get_recent_blog_posts 抛出异常:System.TypeInitializationException:“NHibernate.Cfg.Environment”的类型初始化程序抛出异常。 ---> System.Runtime.Serialization.SerializationException:类型未解析成员 'Castle.DynamicProxy.Serialization.ProxyObjectReference,Rhino.Mocks, Version=3.5.0.1337, Culture=neutral, PublicKeyToken=0b3305902db7183f'..

关于如何调试这里发生的事情有什么想法吗?

【问题讨论】:

    标签: nhibernate


    【解决方案1】:

    我遇到了和你一样的问题——在我的例子中是使用 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 文件访问权限。

    想一想这里有几种方法可以解决这个问题。

    1. 将记录器注入到我的类中,这样它就可以被存根(我想我可能无论如何都应该这样做..)。这将允许我为 Thread 主体使用存根。
    2. 修改线程上现有的 WindowsPrincipal(或基于它创建另一个)以添加调用我的方法所需的角色。

    -- 更新--

    为了解决我的问题,最后我决定按照上面的第一个建议运行。为了避免编写我自己的 NLog Logger 抽象,我只是利用了 Common.Logging 提供的内容。类构造函数现在接受 ILog 作为其参数之一,注入记录器的 Unity 配置如下所示:

    container.RegisterType<ILog>(new TransientLifetimeManager(), new InjectionFactory(x => LogManager.GetCurrentClassLogger()));
    

    同时,我的单元测试现在允许我传入一个模拟记录器。

    var logger = MockRepository.GenerateStub<ILog>();
    

    【讨论】:

      【解决方案2】:

      更多信息...似乎与将 Thread.CurrentPrincipal 切换为模拟的 IPrincipal 实现有关。我在实体内的域模型中进行所有安全检查。在修改实体的属性之前,实体的方法会检查 Thread.CurrentPrincipal.IsInRole()。

      所以,为了测试实体的方法,我必须在调用实体方法之前设置不同的用户(贡献者用户、版主用户等)。

      我还没弄清楚为什么昨天它工作得很好。

      这是我的 Mocked IPrincipal 示例:

              private static IPrincipal _blogContributorUser = null;
          public static IPrincipal BlogContributorUser
          {
              get
              {
                  if (null == _blogContributorUser)
                  {
                      var identity = MockRepository.GenerateStub<IIdentity>(); 
                      identity.Stub(p => p.Name).Return("BlogContributor").Repeat.Any(); 
                      var principal = MockRepository.GenerateStub<IPrincipal>(); 
                      principal.Stub(p => p.Identity).Return(identity).Repeat.Any();
                      principal.Stub(p => p.IsInRole(UserRoles.BlogContributor)).Return(true).Repeat.Any();
                      principal.Stub(p => p.IsInRole(UserRoles.CommentContributor)).Return(true).Repeat.Any();
                      principal.Stub(p => p.IsInRole(UserRoles.TagContributor)).Return(true).Repeat.Any();
                      _blogContributorUser = principal;
                  }
                  return _blogContributorUser;
              }
          }
      

      【讨论】:

        【解决方案3】:

        我也有同样的问题。看起来它在读取配置文件时遇到了问题,因为 CurrentPrincipal 已更改。在替换 CurrentPrincipal(例如,打开 NHibernate 会话、初始化 Unity 等)之前,我已经从配置文件中移动了所有必须初始化的内容,之后一切正常。当然,这不是解决方案,只是一个绝望的人想出的解决方法。

        【讨论】:

          【解决方案4】:

          这样的错误通常表示版本控制问题。

          我怀疑可能发生的事情是 RhinoMocks 和 NHibernate 都在使用 Castle.DynamicProxy 类型,但他们要求该类型的不同版本。

          您最近是否将 RhinoMocks 或 NHibernate 升级到更新版本?

          如果这不是问题,那么更多信息会有所帮助 - 是所有测试都失败了,还是只有这个特定的测试失败了?

          编辑您可能还希望尝试将这些行添加到您的 Properties\AssemblyInfo.cs 文件中:

          [assembly: InternalsVisibleTo("Rhino.Mocks")] 
          [assembly: InternalsVisibleTo("Castle.DynamicProxy")]
          [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
          

          【讨论】:

            【解决方案5】:

            如果错误与使用 RhinoMocks 或 Moq 模拟 IPrincipal 和/或 IIdentity 有关,解决方案实际上非常简单:不要使用这些框架,而是创建简单的假类型。

            这是一个简单的“允许一切”实现的示例:

            public class FakeIdentity : IIdentity
            {
                public string Name { get { return "IntegrationTest"; } }
            
                public string AuthenticationType { get { return "Kerberos"; } }
            
                public bool IsAuthenticated { get { return true; } }
            }
            
            public class FakePrincipal : IPrincipal
            {
                public FakePrincipal() { this.Identity = new FakeIdentity(); }
            
                public IIdentity Identity { get; private set; }
            
                public bool IsInRole(string role) { return true; }
            }
            

            如果您需要更多复杂性,请查看System.Security.Principal.GenericPrincipal 类。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2014-02-16
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2021-03-19
              相关资源
              最近更新 更多