views:

133

answers:

1

I downloaded Rhino Security today and started going through some of the tests. Several that run perfectly in isolation start getting errors after one that purposely raises an exception runs though. Here is that test:

    [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"));
    }

And here are the tests and error messages that fail:

    [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? 

I changed the code to use nunit instead of xunit so maybe that is part of the problem here as well.

Cheers,
Berryl

This is the base class that instantiates the session

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");
    }
}
A: 

How are you instantiating the session?

Whenever there's an exception, the session must be discarded. That also means you should almost never share the session between test methods.

Diego Mijelshon
Ayende's code which instantiates the session in the ctor of a base class is at the end of my original post. Cheers
Berryl
Berryl