C# – How to best handle tests with dates

cdatetimeunit testing

I am using a Repository pattern with filters in my MVC application. The project displays a list of transactions where I can specify a date period to get a subset of transactions, or specify a specific date to get transactions for that date (including year, year/month, and year/month/day views).

I also have functionality for paging getting the next and previous transactions based on what kind of view we are looking at. For example if we are selecting all transactions for a given year/month then I find the next previous and next transactions based on this date period.

How would you go about unit testing for such a thing… here is my mock transaction test repository.

public class TestTransactionsRepository : ITransactionsRepository
{
    private IList<Transaction> db;

    public TestTransactionsRepository()
    {
        db = new List<Transaction>();

        int i = 0;

        for (; i < 10; i++)
        {
            db.Add(CreateTransaction(i, 3));
        }

        for (; i < 25; i++)
        {
            db.Add(CreateTransaction(i, i));
        }

        for (; i < 80; i++)
        {
            db.Add(CreateTransaction(i, 5));
        }
    }

    private Transaction CreateTransaction(int id, int accountID)
    {
        return new Transaction
        {
            ID = id,
            AccountID = accountID,
            Date = ??
        };
     }
}

Here is an example test scnenario.

[TestMethod]
public void TransactionsRepository_Get_With_Filter_Between_ThisDate_
And_ThatDate_Returns_xx_Transactions()
{
    IList<Transaction> transactions = TransactionsRepository.Get()
                                        .Between(thisDate, thatDate)
                                        .ToList();

    Assert.AreEqual(xx, transactions.Count);
}

And then this is my filter method

public static IQueryable<Transaction> Between(
this IQueryable<Transaction> qry, DateTime startDate, DateTime endDate)
{
    return from t in qry
           where t.Date >= startDate && t.Date <= endDate
           select t;
}

Best Answer

You need a variant form of .Add (or of CreateTransaction) that lets you "inject" a (fake) date, exactly for such testing purposes.