如何调试nHibernate/RhinoMocks类型初始值设定项异常
为了调试这一个,我费了好大劲。今天早上早些时候,这个代码运行得很好,我看不出我修改了什么来破坏它。现在,每当我尝试打开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”的类型如何调试nHibernate/RhinoMocks类型初始值设定项异常,nhibernate,Nhibernate,为了调试这一个,我费了好大劲。今天早上早些时候,这个代码运行得很好,我看不出我修改了什么来破坏它。现在,每当我尝试打开nHibernate会话时,都会出现以下错误: 测试方法BCMS.Tests.Repositories.BlogBlogRepositoryTests.can_get_recent_blog_posts引发异常:System.TypeInitializationException:“NHibernate.Cfg.Environment”的类型初始值设定项引发异常。-->Syste
关于如何调试这里发生的事情有什么想法吗?更多信息。。。它似乎与将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文件访问权限
即兴思考以下几种解决此问题的方法
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; }
}