views:

30

answers:

1

I'm trying to create an abstracted layer for ObjectContext. I understand OC is a Unit of Work, but I'm just not entirely how to write a good interface for it. Ideally I'd like to be able to swap out my 'RealDataContext' that implements IDataContext for something like a 'FakeDataContext' that would be fully in-memory.

The reason for this is that I want to be able to test my repositories against an in-memory database.

Thanks!

+2  A: 

You should be able to create an extended class that derives from ObjectContext, and implements an IDataContext interface. To truly be able to mock the ObjectContext, your IDataContext interface would need to include matching signatures (or properties) for any member of ObjectContext that you are using and wish to mock. Something like the following should suffice:

interface IDataContext, IDisposable
{
    void AddObject(string entitySetName, object entity);
    void Attach(IEntityWithKey entity);
    void Detach(object entity);
    void DeleteObject(object entity);
    int SaveChanges();
    int SaveChanges(bool acceptChangesDuringSave);
    int SaveChanges(SaveOptions options);

    // Any other members you wish to be mockable
}

class DataContext: ObjectContext, IDataContext
{
    // nothing here
}

Technically speaking, since DataContext inherits everything from ObjectContect, the implementation of IDataContext is taken care of by ObjectContext. You should not need any additional implementation in the DataContext class. So long as you always inject (or use a factory to create) instances of IDataContext rather than ObjectContext, you should be able to mock IDataContext when testing:

class SomeEntityRepository: IRepository<SomeEntity>
{
    public SomeEntityRepository(IDataContext context)
    {
        m_context = context;
    }

    private readonly IDataContext m_context;

    public SomeEntity GetById(long id)
    {
        // implementation
    }
}

// xUnit.NET & Moq
class SomeEntityRepositoryTests
{
    [Fact]
    public void GetById_returns_entity_when_valid_id_is_passed()
    {
        // state and context
        var mockContext = new Mock<IDataContext>();

        // arrangement
        mockContext.Setup(/* configure mock context here */);
        var repo = new SomeEntityRepository(mockContext.Object);

        // activity
        var entity = repo.GetById(100);

        // assertions
    }
}
jrista
This was the direction I was leaning towards but wasn't really sure if this is a good approach. Thanks!
TheCloudlessSky
Glat to be of service. :)
jrista