views:

218

answers:

2

I have an adapter class for Linq-to-Sql:

public interface IAdapter : IDisposable
{
    Table<Data.User> Activities { get; }
}

Data.User is an object defined by Linq-to-Sql pointing to the User table in persistence.

The implementation for this is as follows:

public class Adapter : IAdapter
{
    private readonly SecretDataContext _context = new SecretDataContext();

    public void Dispose()
    {
        _context.Dispose();
    }

    public Table<Data.User> Users
    {
        get { return _context.Users; }
    }
}

This makes mocking the persistence layer easy in unit testing, as I can just return whatever collection of data I want for Users (Rhino.Mocks):

Expect.Call(_adapter.Users).Return(users);

The problem is that I cannot create the object 'users' since the constructors are not accessible and the class Table is sealed. One option I tried is to just make IAdapter return IEnumerable or IQueryable, but the problem there is that I then do not have access to the methods ITable provides (e.g. InsertOnSubmit()). Is there a way I can create the fake Table in the unit test scenario so that I may be a happy TDD developer?

A: 

My current solution is to wrap the functionality I want from Table into a TableWrapper class:

public interface ITableWrapper<TEntity> 
    where TEntity : class
{
    IEnumerable<TEntity> Collection { get; }
    void InsertOnSubmit(TEntity entity);
}

And here's the implementation:

public class TableWrapper<TEntity> : ITableWrapper<TEntity> 
    where TEntity : class
{
    private readonly Table<TEntity> _table;

    public TableWrapper(Table<TEntity> table)
    {
        _table = table;
    }

    public IEnumerable<TEntity> Collection
    {
        get { return _table; }
    }

    public void InsertOnSubmit(TEntity entity)
    {
        _table.InsertOnSubmit(entity);
    }
}

So now I can easily mock data from Collection, as well as keeping the functionality of InsertOnSubmit (any other functions that I need down the road can be added later on).

Secret Agent Man
A: 

I have had success using the Data Access Layer to produce domain object collections and then using linq to objects. The object under test then only relates to List, which is fairly easy to unit test.

I don't like when the logic entities should have Data Access Layer dependencies. They should stop at the service layer, if even there. I usually go for the model where the service layer invokes a data access object to get a List, passes that list into whichever logic object that needs it (if necessary uses linq-to-objects to filter out the relevant data and injects it into eiter a flat list, dictionary or an object model).

The business objects become very testable, even though they don't benefit from the richness of the inferred data model.

Tormod