chevron-thin-right chevron-thin-left brand cancel-circle search youtube-icon google-plus-icon linkedin-icon facebook-icon twitter-icon toolbox download check linkedin phone twitter-old google-plus facebook profile-male chat calendar profile-male
0 votes
I've got a class, which should work as a Singleton per Thread. It has single static method returing thread-shared object of Isession type (this is NHibernate object).

I've got different tests on it, one of them is to check that actually different instances are returned for different threads (there is also separated test, which checks that instance is the same within one thread; this test is not here).

When test starts, it Mock several type, using DynamicReturnValue. This is crusual, as I need that each mocked invokation of BuildSessionFactory() and OpenSession() actually creates new mocked instance of needed type.

When I start the code and run the test, it shows exception on line:
   session = sessionFactory.OpenSession();

with the message:

Tests.HibernateUtilsTest.CurrentSessionNotNull : TypeMock.VerifyException :
TypeMock Verification: Unexpected Call to NHibernate.ISessionFactory.OpenSession(?)
TearDown : System.Reflection.TargetInvocationException : Exception has been thrown by the target of an invocation.
----> TypeMock.VerifyException :
TypeMock Verification: Expected a new instance of MockISessionFactory (try using MockAll)
Method MockISessionFactory.OpenSession() has 1 more expected calls

And Nunit falls :(

Tested class:

    using NHibernate;
    using NHibernate.Cfg;

    public class HibernateUtils
    {
        private const string CurrentSessionContextKey = "ED88E670-C22D-408a-B2DE-954DC79E1228";
        private static ISessionFactory sessionFactory = null;

        static HibernateUtils()
        {
            Configuration cfg = new Configuration();
            sessionFactory = cfg.BuildSessionFactory();
        }

        public static ISession CurrentSession
        {
            get
            {
                ISession session = ExecutionContext.Current.Items[CurrentSessionContextKey] as ISession;

                if (session == null)
                {
                    session = sessionFactory.OpenSession();
                    ExecutionContext.Current.Items[CurrentSessionContextKey] = session;
                }

                return session;
            }
        }
    }




Fixture:
    [TestFixture]
    public class HibernateUtilsTest : TestBase
    {
        private ISession session;
        private Mock configMockType;
        private MockObject sessionFactoryMockObject;
        private MockObject sessionMockObject;

        [SetUp]
        protected override void TestStart()
        {
            this.MockHibernate();
        }

        protected virtual void MockHibernate()
        {
            configMockType = MockManager.Mock(typeof(Configuration));
            configMockType.AlwaysReturn("BuildSessionFactory", new DynamicReturnValue(CreateSessionFactoryMockObject));
            configMockType.Strict = true;
        }
        protected virtual object CreateSessionFactoryMockObject(object[] parameters, object context)
        {
            sessionFactoryMockObject = MockManager.MockObject(typeof(ISessionFactory));
            sessionFactoryMockObject.ExpectAndReturn("OpenSession", new DynamicReturnValue(CreateSessionMockObject));
            return sessionFactoryMockObject.Object;
        }
        protected virtual object CreateSessionMockObject(object[] parameters, object context)
        {
            sessionMockObject = MockManager.MockObject(typeof(ISession));
            return sessionMockObject.Object;
        }

        [Test]
        public void CurrentSessionDiffersInMutliThreads()
        {
            IList<ISession> sessions = this.GetSessionsFromDifferentThreads(2);
            this.InitSession();
            Assert.AreNotSame(this.session, sessions[0]);
            Assert.AreNotSame(this.session, sessions[1]);
            Assert.AreNotSame(sessions[0], sessions[1]);
        }

        private IList<ISession> GetSessionsFromDifferentThreads(int threadsCount)
        {
            IList<ISession> retList = new List<ISession>();

            for (int i = 0; i < threadsCount; i++)
            {
                this.StartAnotherThreadMethodAndWait(new ThreadStart(this.InitSession));
                retList.Add(this.session);
            }

            return retList;
        }

        protected virtual void StartAnotherThreadMethodAndWait(ThreadStart methodToStart)
        {
            Thread anotherThread = new Thread(methodToStart);
            anotherThread.Start();
            anotherThread.Join();
        }

        public void InitSession()
        {
            this.session = HibernateUtils.CurrentSession;
        }
}
asked by ezaritov (2.8k points)

4 Answers

0 votes
Hi,
It seems as though sessionFactory.OpenSession(); is called 3 times,
2 times from GetSessionsFromDifferentThreads and once directly from the test.

but the expectation is set to ONE time only called by sessionFactoryMockObject.ExpectAndReturn("OpenSession"...
You should change this to 3 times or use AlwaysReturn, depending on whether you want to verify that the method was called exacly 3 times.

As MockObjects are Strict, the second time OpenSession is called will fail.
I hope this helps
answered by scott (32k points)
0 votes
After some further investigation, creating mocks inside DynamicReturnValue delegated (while inside a mocked method) is not supported.
This will be considered for future versions.
answered by scott (32k points)
0 votes
Thank you scott again. The last answer was what I expected. I actually gave a wrong code example. the correct one should be with AlwaysReturn. So, the right answer is that creating of mock dynamically from DynamicReturnValue is not supported. It'a pity :)

Ok, I hope I will find a workaround about this by rearranging tests. Hope that this functionality will be availablу soon, not in few years :)
answered by ezaritov (2.8k points)
0 votes
Hi,
This is implemented in version 3.1 for Enterprise Editions
answered by scott (32k points)
...