如何调试nHibernate/RhinoMocks类型初始值设定项异常

如何调试nHibernate/RhinoMocks类型初始值设定项异常,nhibernate,Nhibernate,为了调试这一个,我费了好大劲。今天早上早些时候,这个代码运行得很好,我看不出我修改了什么来破坏它。现在,每当我尝试打开nHibernate会话时,都会出现以下错误: 测试方法BCMS.Tests.Repositories.BlogBlogRepositoryTests.can_get_recent_blog_posts引发异常:System.TypeInitializationException:“NHibernate.Cfg.Environment”的类型初始值设定项引发异常。-->Syste

为了调试这一个,我费了好大劲。今天早上早些时候,这个代码运行得很好,我看不出我修改了什么来破坏它。现在,每当我尝试打开nHibernate会话时,都会出现以下错误:

测试方法BCMS.Tests.Repositories.BlogBlogRepositoryTests.can_get_recent_blog_posts引发异常:System.TypeInitializationException:“NHibernate.Cfg.Environment”的类型初始值设定项引发异常。-->System.Runtime.Serialization.Serialization异常:未解析成员“Castle.DynamicProxy.Serialization.ProxyObjectReference,Rhino.Mocks,版本=3.5.0.1337,区域性=中性,PublicKeyToken=0b3305902db7183f”的类型


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

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

因此,为了测试实体的方法,我必须在调用实体方法之前设置不同的用户(参与者用户、主持人用户等)

我还没弄明白为什么昨天这样做效果很好

以下是我被嘲笑的原则的一个例子:

        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;
        }
    }
private static IPrincipal\u blogContributorUser=null;
公共静态IPrincipal BlogContributorUser
{
得到
{
if(null==\u blogContributorUser)
{
var identity=MockRepository.GenerateStub();
identity.Stub(p=>p.Name).Return(“BlogContributor”).Repeat.Any();
var principal=MockRepository.GenerateStub();
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=委托人;
}
return\u blogContributorUser;
}
}

像这样的错误通常表明存在版本控制问题

我怀疑Rhinomock和NHibernate都在使用Castle.DynamicProxy类型,但他们要求的是该类型的不同版本

你最近有没有把Rhinomock或NHibernate升级到新版本

如果这不是问题所在,那么更多的信息将是有帮助的——是所有测试都失败了,还是只有这一个测试失败了

编辑您可能还希望尝试将以下行添加到Properties\AssemblyInfo.cs文件:

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

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

我遇到了与您相同的问题-在我的案例中,是使用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;
因此,正如您从堆栈跟踪中看到的那样,尝试读取配置文件是无效的-为什么?因为现在模拟的当前主体不再是我们原来的WindowsPrincipal,它现在是一个模拟主体,没有任何windows文件访问权限

即兴思考以下几种解决此问题的方法

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

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

    container.RegisterType<ILog>(new TransientLifetimeManager(), new InjectionFactory(x => LogManager.GetCurrentClassLogger()));
    
    container.RegisterType(新TransientLifetimeManager(),新InjectionFactory(x=>LogManager.GetCurrentClassLogger());
    
    同时,我的单元测试现在允许我通过模拟记录器

    var logger = MockRepository.GenerateStub<ILog>();
    
    var logger=MockRepository.GenerateStub();
    
    如果错误与使用Rhinomock或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; }
    }
    
    如果您需要更多的复杂性,请查看该类

    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; }
    }