Mocking a low layer

2 posts, 0 answers
  1. Michael Kogan
    Michael Kogan avatar
    2 posts
    Member since:
    May 2010

    Posted 05 Aug 2013 Link to this post

    Hi,

    suppose my applicaiton contains several layers, the lowest one is a DAL (Data Access Layer) interfacing with a DB.
    Now, I want to unit-test a method of a class in the upper layer which eventually calls a method in the DAL. Naturally, I want to mock only the DB, not the mid-layer classes.
    How should I go about unit-testing a high-layer method as mentioned above?

    Thanks,
    Michael
  2. Kaloyan
    Admin
    Kaloyan avatar
    872 posts

    Posted 08 Aug 2013 Link to this post

    Hi Michael Kogan,

    Thank you for contacting Telerik support.

    Normally, you will need to mock the interfaces/classes in the DAL and pass these mocks to your SUT (the upper layer classes). I have added a simple example explaining how this can be achieved:

    Let's assume we have the following DB:
    public class Dinner
    {
        public int DinnerID { get; set; }
         
        public string Title { get; set; }
         
        public DateTime EventDate { get; set; }
         
        public string Address { get; set; }
         
        public string HostedBy { get; set; }
    }
     
    And for it we will be using a custom CRUD operations (this is our DAL):
    public interface IMaintanable<T>
    {
        void Create(T obj);
        T Retrieve(int key);
        void Update(T obj);
        void Delete(int key);
    }
     
    public class DinnerManager : IMaintanable<Dinner>
    {
        public void Create(Dinner obj)
        {
            // Inserts record in the DB.
            throw new NotImplementedException();
        }
     
        public Dinner Retrieve(int dinnerId)
        {
            // Retrieves record from the DB.
            throw new NotImplementedException();
        }
     
        public void Update(Dinner obj)
        {
            // Updates the record in the DB.
            throw new NotImplementedException();
        }
     
        public void Delete(int dinnerId)
        {
            // Deletes record from the DB.
            throw new NotImplementedException();
        }
    }
    As you can see, the CRUD operations are not even implemented.

    Then we have an upper layer class, with some logic in it:
    public class SUT
    {
        private IMaintanable<Dinner> dinnerManager;
         
        public SUT(IMaintanable<Dinner> manager)
        {
            this.dinnerManager = manager;
        }
     
        public string GetAndFormatDinnerInfo(int dinnerID)
        {
            StringBuilder info = new StringBuilder();
     
            Dinner checkedDinner = dinnerManager.Retrieve(dinnerID);
     
            info.AppendFormat("Title: {0} \n", checkedDinner.Title);
            info.AppendFormat("DinnerID: {0} \n", checkedDinner.DinnerID);
            info.AppendFormat("EventDate: {0} \n", checkedDinner.EventDate.Date);
            info.AppendFormat("Address: {0} \n", checkedDinner.Address);
            info.AppendFormat("HostedBy: {0}", checkedDinner.HostedBy);
             
            return info.ToString();
        }
    }
    We need to test the GetAndFormatDinnerInfo method. For it, we will need to isolate one of our DAL methods that is still not implemented (the Retrieve() method).

    Here is how this can be done:
    [TestMethod]
    public void GetAndFormatDinnerInfo_OnExecuteWithMockedDB_ShouldReturnExpected()
    {
        // This will be our fake Dinner.
        //  We will use it as a return value to the mocked Retrieve method.
        var fakeDinner = new Dinner()
        {
            DinnerID = 1,
            Title = "FakeDinner 1",
            EventDate = new DateTime(1222, 12, 12),
            Address = "Fake Address 1",
            HostedBy = "Fake Host 1"
        };
     
        // ARRANGE
        // Creating a mocked instance of the generic IMaintanable<Dinner> interface.
        var iMaintanable = Mock.Create<IMaintanable<Dinner>>();
     
        // Arranging: When the Retrieve method is called with any string as an argument,
        //  it should return fakeDinner.
        Mock.Arrange(() => iMaintanable.Retrieve(1)).Returns(fakeDinner);
     
        // ACT
        // Creating an actual instance of our class under test.
        var actualSUT = new SUT(iMaintanable);
        var actualDinner = actualSUT.GetAndFormatDinnerInfo(1);
     
        // ASSERT - Asserting against the expected values.
        Assert.AreEqual(
            "Title: FakeDinner 1 \n" +
            "DinnerID: 1 \n" +
            "EventDate: 12/12/1222 12:00:00 AM \n" +
            "Address: Fake Address 1 \n" +
            "HostedBy: Fake Host 1",
            actualDinner);
    }
    The above works even with the free version of JustMock, as we are mocking an interface. However, there are a lot more possibilities if using JustMock commercial. Please, check these articles for more information: 1, 2

    I hope this helps. Please, let me know if you need further assistance, or there is anything specific you would like how to isolate/mock with our tool :).

    Regards,
    Kaloyan
    Telerik
    Share what you think about JustTrace & JustMock with us, so we can become even better! You can use the built-in feedback tool inside JustTrace, our forums, or our JustTrace or JustMock portals.
  3. DevCraft R3 2016 release webinar banner
Back to Top