2009-04-22 5 views
2

Retirer mes cheveux en essayant de déboguer celui-ci. Plus tôt ce matin, ce code fonctionnait bien, et je ne vois pas ce que j'ai changé pour le casser. Maintenant, chaque fois que je tente d'ouvrir une session NHibernate, je reçois l'erreur suivante:Comment déboguer l'exception TypeInitializer de nHibernate/RhinoMocks

Méthode d'essai BCMS.Tests.Repositories.BlogBlogRepositoryTests.can_get_recent_blog_posts jeté exception: System.TypeInitializationException: Le type initialiseur pour « NHibernate.Cfg. Environnement 'a jeté une exception. ---> System.Runtime.Serialization.SerializationException: Le type n'est pas résolu pour le membre 'Castle.DynamicProxy.Serialization.ProxyObjectReference, Rhino.Mocks, Version = 3.5.0.1337, Culture = neutre, PublicKeyToken = 0b3305902db7183f' ..

Des idées sur la façon de déboguer ce qui se passe ici?

+0

Avez-vous une partie du code? –

Répondre

1

Plus d'informations ... il semble être lié à la commutation du Thread.CurrentPrincipal à une implémentation IPrincipal mockée. Je fais tous mes contrôles de sécurité dans mon modèle de domaine à l'intérieur des entités. Les méthodes de l'entité vérifient Thread.CurrentPrincipal.IsInRole() avant de modifier les propriétés de l'entité. Donc, pour tester les méthodes de l'entité, je dois définir différents utilisateurs (utilisateur contributeur, utilisateur modérateur, etc.) avant de faire mes appels de méthode d'entité.

Je n'ai pas compris pourquoi cela fonctionnait bien hier.

Voici un exemple de mon Raillé 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; 
     } 
    } 
1

Des erreurs comme celle-ci indiquent généralement des questions versioning. Ce que je soupçonne peut-être que RhinoMocks et NHibernate utilisent le type Castle.DynamicProxy, mais ils demandent des versions différentes de ce type.

Avez-vous récemment actualisé RhinoMocks ou NHibernate à une version plus récente?

Si ce n'est pas le problème, alors plus d'informations seraient utiles - tous les tests échouent, ou juste celui-ci en particulier?

modifier Vous pouvez également essayer d'ajouter ces lignes à votre fichier Propriétés \ AssemblyInfo.cs:

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

J'ai la même question. Il semble qu'il a du mal à lire le fichier de configuration, puisque CurrentPrincipal est modifié. J'ai déplacé tout ce qui doit être initialisé à partir du fichier de configuration, avant de remplacer le CurrentPrincipal (par exemple, la session NHibernate ouverte, Unity initialisé et ce genre de choses), et tout fonctionne après cela. Bien sûr, ce n'est pas une solution, juste une solution de contournement trouvée par un homme désespéré.

2

je frappe la même question que vous - dans mon cas, il était avec la méthode statique NLog:

LogManager.GetCurrentClassLogger() 

j'avais remplacé le principal thread courant avec un talon 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; 

Course à pied tests unitaires pour mon code a jeté la même exception de la question initiale.

La trace de la pile:

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... 

Comme vous pouvez le voir à partir de la pile trace une tentative de lire le fichier de configuration est fait, ce qui ne fonctionne pas - pourquoi? Parce que le principal courant actuellement mocké n'est plus le WindowsPrincipal que nous avions à l'origine - c'est maintenant un principal mocked qui n'aura aucune sorte d'accès de fichier de Windows.

Penser à la manchette Voici quelques façons de résoudre ce problème.

  1. Injecter l'enregistreur dans ma classe pour qu'il puisse être écrasa (je devrais probablement faire cela de toute façon je suppose ..). Cela me permettrait d'utiliser un talon pour le chef de file.
  2. Modifiez le WindowsPrincipal existant (ou créez-en un autre sur la base de ce thread) pour ajouter les rôles requis pour appeler mes méthodes.

- MISE À JOUR -

Pour résoudre mon problème, à la fin j'ai décidé de courir avec ma première suggestion ci-dessus. Pour éviter d'écrire ma propre abstraction du NLog Logger, j'ai simplement exploité ce qui était offert par Common.Logging. Les constructeurs de classe acceptent maintenant ILog comme l'un de leurs paramètres, et la configuration Unity pour injecter l'enregistreur ressemble à ceci:

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

Pendant ce temps, mes tests unitaires me permettent maintenant de passer dans un enregistreur moqué.

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

Si l'erreur est liée à moqueuse IPrincipal et/ou IIdentity avec RhinoMocks ou Moq la solution est en fait assez simple: ne pas utiliser ces cadres mais créent des types simples faux.

Voici un exemple pour une implémentation simple « de tout permettre »:

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

Si vous avez besoin plus de complexité jeter un oeil à la classe System.Security.Principal.GenericPrincipal.

Questions connexes