拔掉我的头发试图调试这个。今天早上早些时候,这段代码工作正常,我看不出我改变了什么来打破它。现在,每当我尝试打开一个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'..
有关如何调试此处发生的事情的想法吗?
答案 0 :(得分:2)
我和你一样遇到了同样的问题 - 就我而言,这是用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文件访问。
在这里思考袖口有两种方法可以解决这个问题。
- 更新 -
为了解决我的问题,最后我决定按照上面的第一个建议运行。为了避免编写我自己的NLog Logger抽象,我只是利用了Common.Logging提供的东西。类构造函数现在接受ILog作为它们的参数之一,并且注入记录器的Unity配置看起来像这样:
container.RegisterType<ILog>(new TransientLifetimeManager(), new InjectionFactory(x => LogManager.GetCurrentClassLogger()));
与此同时,我的单元测试现在允许我传入一个模拟的记录器。
var logger = MockRepository.GenerateStub<ILog>();
答案 1 :(得分:1)
更多信息......它似乎与将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;
}
}
答案 2 :(得分:1)
这样的错误通常表明版本问题。
我怀疑可能发生的是RhinoMocks和NHibernate都在使用Castle.DynamicProxy类型,但他们要求使用该类型的不同版本。
您最近是否将RhinoMocks或NHibernate升级为新版本?
如果这不是问题,那么更多信息会有所帮助 - 所有测试都失败了,还是仅仅是这个?
编辑您可能还想尝试将这些行添加到Properties \ AssemblyInfo.cs文件中:
[assembly: InternalsVisibleTo("Rhino.Mocks")]
[assembly: InternalsVisibleTo("Castle.DynamicProxy")]
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
答案 3 :(得分:0)
我有同样的问题。看起来它在阅读配置文件时遇到了麻烦,因为CurrentPrincipal已经更改。在更换CurrentPrincipal(例如,打开NHibernate会话,初始化Unity和那种东西)之前,我已经将所有必须从配置文件初始化的内容移动了,之后一切正常。当然,这不是一个解决方案,只是一个绝望的人所解决的解决方法。
答案 4 :(得分:0)
如果错误与使用RhinoMocks或Moq模拟IPrincipal
和/或IIdentity
有关,解决方案实际上非常简单:不要使用这些框架,而是创建简单的假类型。
这是一个简单的例子&#34;允许一切&#34;实现:
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
类。