CathalMF
CathalMF

Reputation: 10055

Unit Testing class which communicates with a database

Ok Lets assume i have a class which controls my data layer and a class which performs the work.

class MyData
{
    public DataTable GetMyData()
    {
         return Query.MyDataBase.ResultDT();
    }
}

class MyWork
{
    public int DoWork()
    {
        MyData Data = new MyData();
        DataTable DT = Data.GetMyData();
        return DT.Rows.Count;
    }
}

How can i test my DoWork method with a unit test without accessing the database.

[TestMethod()]
public void TestMyWork()
{
    MyWork work = new MyWork();
    int result = work.DoWork();
    Assert.AreEqual(1, result);
}

Upvotes: 2

Views: 54

Answers (2)

Jakub Lortz
Jakub Lortz

Reputation: 14896

First, follow @toadflakz advice and inject MyData to MyWork's constructor.

Then, use some ORM to map the data from the db to objects. Don't use DataTable.

To make DoWork easier to test, consider refactoring it into a pure function:

public int DoWork(DataTable dt)
{
    // make some complex calculations on dt
}

This way the result of DoWork depends only on the input parameter, which makes it very easy to test.

Upvotes: 1

toadflakz
toadflakz

Reputation: 7944

Make the MyData class a dependency parameter and inject it during construction of your MyWork class. For unit testing purposes, mock the dependency in your unit test to ensure that it is calling the defined dependency's contract in an expected manner.

Typically this means:

  • Defining an interface for the dependency i.e. IMyData
  • The constructor signature should expect the interface type rather than the concrete type.

As a final result, your code would be transformed as follows:

interface IMyData
{
    DataTable GetMyData();
}

class MyData : IMyData
{
    public DataTable GetMyData()
    {
         return Query.MyDataBase.ResultDT();
    }
}

class MyWork
{
    private IMyData _myData;

    public MyWork(IMyData myData)
    {
        _myData = myData;
    }

    public int DoWork()
    {
        DataTable DT = _myData.GetMyData();
        return DT.Rows.Count;
    }
}

As a step further, you should check out the SOLID design principles as this type of design demonstrates why they exist.

More on Wikipedia: SOLID (OO design)

Edit:

Your unit test would then look something like (assuming you're using the Moq mocking framework):

[TestMethod()]
public void TestMyWork()
{
    var mockMyData = Mock<IMyData>();
    mockMyData.Setup(x => x.GetMyData()).Returns(new DataTable());

    MyWork work = new MyWork(mockMyData);
    int result = work.DoWork();
    Assert.AreEqual(1, result);
}

..but in the real world you would more than likely instantiate MyWork with a real MyData instance as follows (unless you're using a Dependency Injection framework such as MEF or Unity):

var myWork = new MyWork(new MyData());

Upvotes: 5

Related Questions