This is a migrated thread and some comments may be shown as answers.

Mocking a low layer

1 Answer 85 Views
General Discussions
This is a migrated thread and some comments may be shown as answers.
Michael Kogan
Top achievements
Rank 1
Michael Kogan asked on 05 Aug 2013, 10:25 AM
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

1 Answer, 1 is accepted

Sort by
0
Kaloyan
Telerik team
answered on 08 Aug 2013, 07:41 AM
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.
Tags
General Discussions
Asked by
Michael Kogan
Top achievements
Rank 1
Answers by
Kaloyan
Telerik team
Share this question
or