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
How to unit test the following code? this is a NHibernate application. The governing philosophy is that mocks/ stubs should be kept to minimum. It is best if I could just return a fake object when I call DBFactory.Factory.OpenSession(), and proceed to manipulate it as if it's a real object.

And finally I just assert that the proper objects are saved.

        public static void UpdateName(int id, string newName)
        {
            using (ISession session = DBFactory.Factory.OpenSession())
            {
                var firstSession = session.Load<Site>(id);
                firstSession.Name = newName;
                session.SaveOrUpdate(firstSession);
                session.Flush();

            }
        }
asked by nsoonhui (59.1k points)

2 Answers

0 votes
Maybe this will work for you.
I have collapsed the DBFactory calls into one call to simplify and created classes so I could run without installing NHibernate :)

    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void Test()
        {
            //Arrange
            Site s = new Site { Name = "newname" };
            ISession fakeSession = Isolate.Fake.Instance<ISession>();
            Isolate.WhenCalled(() => 
                DBFactory.OpenSession())
                .WillReturn(fakeSession);
            Isolate.WhenCalled(() => 
                fakeSession.Load<Site>(1))
                .WillReturn(s);
            Test t = new Test();

            //Act
            t.UpdateName(1, "newname");

            //Assert
            Isolate.Verify.WasCalledWithExactArguments(() => fakeSession.SaveOrUpdate(s));
        }
    }
    class Test
    {
        public void UpdateName(int id, string newName)
        {
            using (ISession session = DBFactory.OpenSession())
            {
                var firstSession = session.Load<Site>(id);
                firstSession.Name = newName;
                session.SaveOrUpdate(firstSession); //this one passes the test
                Site s = new Site() { Name = "fred" };
                //session.SaveOrUpdate(s); //this one fails the test
                session.Flush();
            }
        }
    }
    public interface ISession : IDisposable
    {
        T Load<T>(int id) where T : new();
        void SaveOrUpdate(object s);
        void Flush();
    }
    class DBFactory
    {
        public static ISession OpenSession()
        {
            return new Session();
        }
    }
    class Session : ISession
    {

        #region ISession Members

        public void SaveOrUpdate(object s)
        {
            throw new NotImplementedException();
        }

        public void Flush()
        {
            throw new NotImplementedException();
        }

        public T Load<T>(int id) where T : new()  
        {
            return new T();
        }

        #endregion

        #region IDisposable Members

        public void Dispose()
        {
        }

        #endregion
    }
    public class Site 
    {
        public string Name { get; set; }
    }
answered by andredking (800 points)
0 votes
Hi andredking,

actually, that's the thing that I want to avoid. Your example seems to use a lot of mocks and fakes-- and this is something that I don't like because this will make the test brittle.

It would be better if I can return a fake object when I call DBFactory.OpenSession(), and then proceed to manipulate it as if it's a real object.

The hard part, I think, is to come up with a fake ISession object that
  1. is an accurate representation of the real object
  2. hides enough irrelevant details.
[/list]
answered by nsoonhui (59.1k points)
...