15

Currently I'm using EF6 to implement my repositories inside a UnitOfWork. I also have created an In-Memory mock implementations (MockUnitOfWork & MockRepository) so that I can use them in unit tests, however I now have to deal with the tedious setup of the objects.

Isn't this what Autofixture is designed to do? How would I go about getting a MockUnitOfWork that I can use in my tests that contains Foo and Barr repositories that are populated? I'm using NSubstitute for my mocking framework.

IUnitOfWork

public interface IUnitOfWork
{
    void Save();
    void Commit();
    void Rollback();

    IRepository<Foo> FooRepository { get; }
    IRepository<Bar> BarRepository { get; }
}

IRepository

public interface IRepository<TEntity> where TEntity : class
{
    Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, string         includeProperties = "");

    IEnumerable<TEntity> Get(Expression<Func<TEntity, bool>> filter = null, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null);
    TEntity GetByID(object id);

    void Insert(TEntity entity);
    void Delete(object id);
    void Delete(TEntity entityToDelete);
    void Update(TEntity entityToUpdate);
}
Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
WhiskerBiscuit
  • 4,795
  • 8
  • 62
  • 100
  • 2
    You have to use the [AutoFixture.AutoNSubStitute](https://www.nuget.org/packages/AutoFixture.AutoNSubstitute) auto-mocking extension. You can learn more about it [here](http://stackoverflow.com/a/12871065/467754). If you are using xUnit.net you may also look [here](http://nikosbaxevanis.com/blog/2012/07/31/autofixture-xunit-dot-net-and-auto-mocking/). – Nikos Baxevanis Mar 12 '14 at 07:06
  • 3
    As @NikosBaxevanis says, the Glue Library that binds AutoFixture and NSubstitute together is AutoFixture.AutoNSubstitute. However, it's probably not going to do what you hope it'll do, because it can't *populate* your repositories. AutoFixture is good at filling *data* in object graphs, but a mock doesn't contain *data*, it exposes *behaviour*, which is an entirely different thing. In order to give a mock the correct behaviour, you'll have to configure it. That's more an NSubstitute question than an AutoFixture question, so I've added the *nsubstitute* tag. – Mark Seemann Mar 12 '14 at 09:24
  • The way I understand it is I have two options. 1) Use Nsub/moq type framework to simulate the behavior of the UOW 2) Use a concrete double of my IUnitOfWork and populate it with test data. Does that sound correct? – WhiskerBiscuit Mar 12 '14 at 20:27
  • take a look at effort. going that irepository+mocking route is just a world of hurt. ive tried, it didnt go well. https://effort.codeplex.com/ – eatfrog Jul 08 '14 at 13:25
  • TBH, I agree with frog, its not worth the effort. Right now we are using transactions to restore databases after testing. – WhiskerBiscuit Jul 10 '14 at 13:51
  • Just FYI, if you were using Moq, `AutoConfiguredMoqCustomization` (available as of 3.20.0) would fulfill your requirements. – dcastro Aug 21 '14 at 18:25

2 Answers2

1

You're trying to do functional testing here, so it would be wise to have a functional database.

EF can recreate and destroy your database in your setup and teardown methods with a test connection string. This would provide a real functional testing environment for your tests to operate against mimicking the real environment.

Ex:

        [TestFixtureSetUp]
        public static void SetupFixture() //create database
        {
            using (var context = new XEntities())
            {
                context.Setup();
            }
        }

        [TestFixtureTearDown]
        public void TearDown() //drop database
        {
            using (var context = new XEntities())
            {
                context.Database.Delete();
            }
        }

        [SetUp]
        public void Setup() //Clear entities before each test so they are independent
        {
            using (var context = new XEntities())
            {
                foreach (var tableRow in context.Table)
                {
                    context.Table.Remove(tableRow);
                }
                context.SaveChanges();
            }
        }
C Bauer
  • 5,003
  • 4
  • 33
  • 62
0

Yes, this is exactly what it's designed to do. See the example below. I'm using Mock instead of NSubstitute, because I'm not familiar with NSubstitute. You'll just have to pass another customization, and use NSubstitute syntax in setups.

[SetUp]
public  void SetUp()
{
    // this will make AutoFixture create mocks automatically for all dependencies
    _fixture = new Fixture()
         .Customize(new AutoMoqCustomization()); 

    // whenever AutoFixture needs IUnitOfWork it will use the same  mock object
    // (something like a singleton scope in IOC container)
    _fixture.Freeze<Mock<IUnitOfWork>>(); 

    // suppose YourSystemUnderTest takes IUnitOfWork as dependency,
    // it'll get the one frozen the line above
    _sut = _fixture.Create<YourSystemUnderTest>(); 
}

[Test]
public void SomeTest()
{
    var id = _fixture.Create<object>(); // some random id
    var fooObject = _fixture.Create<Foo>(); // the object repository should return for id

    // setuping THE SAME mock object that wa passed to _sut in SetUp.
    // _fixture.Freeze<Mock part is ESSENTIAL
    // _fixture.Freeze<Mock<IUnitOfWork>>() returns the mock object, so whatever comes
    // next is Mock specific and you'll have to use NSubstitute syntax instead
    _fixture.Freeze<Mock<IUnitOfWork>>()
            .Setup(uow => uow.FooRepository.GetById(id))
            .Returns(fooObject); 

    // if this method will ask the unit of work for FooRepository.GetById(id)
    // it will get fooObject.
    var whatever = _sut.SomeMethod(id); 

    // do assertions
}

The beautiful thing about AutoFixture is that you don't have to create mocks for all of the dependencies of your system under test. If you're testing a functionality that uses only one dependency, you just Freeze it before creating the system under test. The rest of the dependencies will be mocked automatically.

Andrzej Gis
  • 13,706
  • 14
  • 86
  • 130