nhibernate错误修复

问题描述:

我今天下载了Rhino Security,并开始进行一些测试。几个独立完美运行的开始出现错误之后,会故意引发异常。下面是测试:nhibernate错误修复

[Test] 
    public void EntitiesGroup_IfDuplicateName_Error() { 
     _authorizationRepository.CreateEntitiesGroup("Admininstrators"); 

     _session.Flush(); 

     var ex = Assert.Throws<GenericADOException>(
      () => 
       { 
        _authorizationRepository.CreateEntitiesGroup("Admininstrators"); 
        _session.Flush(); 
       }).InnerException; 

     Assert.That(ex.Message, Is.StringContaining("unique")); 
    } 

,这里是失败的试验和错误消息:

[Test] 
    public void User_CanSave() { 
     var ayende = new User {Name = "ayende"}; 
     _session.Save(ayende); 
     _session.Flush(); 
     _session.Evict(ayende); 

     var fromDb = _session.Get<User>(ayende.Id); 
     Assert.That(fromDb, Is.Not.Null); 
     Assert.That(ayende.Name, Is.EqualTo(fromDb.Name)); 
    } 

    ----> System.Data.SQLite.SQLiteException : Abort due to constraint violation column Name is not unique 


    [Test] 
    public void UsersGroup_CanCreate() 
    { 
     var group = _authorizationRepository.CreateUsersGroup("Admininstrators"); 

     _session.Flush(); 
     _session.Evict(group); 

     var fromDb = _session.Get<UsersGroup>(group.Id); 
     Assert.NotNull(fromDb); 
     Assert.That(fromDb.Name, Is.EqualTo(group.Name)); 
    } 

failed: NHibernate.AssertionFailure : null id in Rhino.Security.Tests.User entry (don't flush the Session after an exception occurs) 

Does anyone see how I can reset the state of the in memory SQLite db after the first test? 

我改变了代码使用NUnit代替的xUnit所以也许这就是问题的一部分这里好。

干杯,
Berryl

这是实例化会话的基类

public abstract class DatabaseFixture : IDisposable 
{ 
    protected Account _account; 
    protected IAuthorizationRepository _authorizationRepository; 
    protected IAuthorizationService _authorizationService; 
    protected IPermissionsBuilderService _permissionsBuilderService; 
    protected IPermissionsService _permissionService; 
    protected User _user; 

    protected ISession _session; 
    protected readonly ISessionFactory _factory; 

    protected DatabaseFixture() 
    { 
     BeforeSetup(); 

     SillyContainer.SessionProvider = (() => _session); 
     var sillyContainer = new SillyContainer(); 
     ServiceLocator.SetLocatorProvider(() => sillyContainer); 

     Assert.NotNull(typeof(System.Data.SQLite.SQLiteConnection)); 

     var cfg = new Configuration() 
      .SetProperty(Environment.ConnectionDriver, typeof(SQLite20Driver).AssemblyQualifiedName) 
      .SetProperty(Environment.Dialect, typeof(SQLiteDialect).AssemblyQualifiedName) 
      .SetProperty(Environment.ConnectionString, ConnectionString) 
      .SetProperty(Environment.ProxyFactoryFactoryClass, typeof(ProxyFactoryFactory).AssemblyQualifiedName) 
      .SetProperty(Environment.ReleaseConnections, "on_close") 
      .SetProperty(Environment.UseSecondLevelCache, "true") 
      .SetProperty(Environment.UseQueryCache, "true") 
      .SetProperty(Environment.CacheProvider,typeof(HashtableCacheProvider).AssemblyQualifiedName) 
      .AddAssembly(typeof (User).Assembly); 

     Security.Configure<User>(cfg, SecurityTableStructure.Prefix); 

     _factory = cfg.BuildSessionFactory(); 

     _session = _factory.OpenSession(); 

     new SchemaExport(cfg).Execute(false, true, false, _session.Connection, null); 

     _session.BeginTransaction(); 

     SetupEntities(); 

     _session.Flush(); 
    } 

    protected virtual void BeforeSetup() { } 

    public virtual string ConnectionString { get { return "Data Source=:memory:"; } } 

    public void Dispose() 
    { 
     if (_session.Transaction.IsActive) 
      _session.Transaction.Rollback(); 
     _session.Dispose(); 
    } 

    private void SetupEntities() 
    { 
     _user = new User {Name = "Ayende"}; 
     _account = new Account {Name = "south sand"}; 

     _session.Save(_user); 
     _session.Save(_account); 

     _authorizationService = ServiceLocator.Current.GetInstance<IAuthorizationService>(); 
     _permissionService = ServiceLocator.Current.GetInstance<IPermissionsService>(); 
     _permissionsBuilderService = ServiceLocator.Current.GetInstance<IPermissionsBuilderService>(); 
     _authorizationRepository = ServiceLocator.Current.GetInstance<IAuthorizationRepository>(); 

     _authorizationRepository.CreateUsersGroup("Administrators"); 
     _authorizationRepository.CreateEntitiesGroup("Important Accounts"); 
     _authorizationRepository.CreateOperation("/Account/Edit"); 


     _authorizationRepository.AssociateUserWith(_user, "Administrators"); 
     _authorizationRepository.AssociateEntityWith(_account, "Important Accounts"); 
    } 
} 
+0

我将新会话的开始和创建SQLite数据库提取到Setup方法中,并将_session.Dispose放入Teardown方法中,以便运行所有测试。如果有人能够看到Ayende&XUnit如何完成这项工作,我会稍微留意一下。干杯 – Berryl 2010-05-18 19:46:04

你是如何实例化会话?

每当发生异常时,都必须丢弃该会话。这也意味着你几乎不应该在测试方法之间共享会话。

+0

Ayende在基类的ctor中实例化会话的代码是在我原来的帖子的末尾。干杯 – Berryl 2010-05-18 15:23:54

+0

Ayende在每次测试后都会处理会话,但是使用XUnit和一个IDisposable基础设备来完成,而不是我个人比较熟悉的NUnit Teardown方法。这对于SQLite来说很有意义,因为重新生成数据库非常快。我在使用“真实”数据库的测试之间看到的另一种方法是每次测试开始和回滚事务。 – Berryl 2010-05-27 15:28:31