Как я могу создать и заполнить свои фиктивные классы с помощью Autofixture?

В настоящее время я использую EF6 для реализации своих репозиториев внутри UnitOfWork. Я также создал фиктивные реализации In-Memory (MockUnitOfWork и MockRepository), чтобы использовать их в модульных тестах, однако теперь мне приходится иметь дело с утомительной настройкой объектов.

Разве не для этого предназначен Autofixture? Как мне получить MockUnitOfWork, который я могу использовать в своих тестах, который содержит заполненные репозитории Foo и Barr? Я использую NSubstitute для своей насмешливой структуры.

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);
}

person WhiskerBiscuit    schedule 12.03.2014    source источник
comment
Вы должны использовать расширение автоматического макетирования AutoFixture.AutoNSubStitute. Подробнее об этом можно узнать здесь. Если вы используете xUnit.net, вы также можете посмотреть здесь.   -  person Nikos Baxevanis    schedule 12.03.2014
comment
Как говорит @NikosBaxevanis, библиотека Glue, которая связывает AutoFixture и NSubstitute, называется AutoFixture.AutoNSubstitute. Однако он, вероятно, не будет делать то, на что вы надеетесь, потому что он не может заполнить ваши репозитории. AutoFixture хорошо заполняет данными графы объектов, но макет не содержит данные, он показывает поведение, а это совсем другое. . Чтобы дать макету правильное поведение, вам нужно его настроить. Это скорее вопрос NSubstitute, чем вопрос AutoFixture, поэтому я добавил тег nsubstitute.   -  person Mark Seemann    schedule 12.03.2014
comment
Я так понимаю, что у меня есть два варианта. 1) Используйте структуру типа Nsub/moq для имитации поведения UOW. 2) Используйте конкретную копию моего IUnitOfWork и заполните ее тестовыми данными. Это звучит правильно?   -  person WhiskerBiscuit    schedule 13.03.2014
comment
посмотрите на усилие. Идти по этому маршруту репозиторий + насмешка - это просто мир боли. пробовал, не получилось. effort.codeplex.com   -  person eatfrog    schedule 08.07.2014
comment
TBH, я согласен с лягушкой, это не стоит усилий. Прямо сейчас мы используем транзакции для восстановления баз данных после тестирования.   -  person WhiskerBiscuit    schedule 10.07.2014
comment
К вашему сведению, если бы вы использовали Moq, AutoConfiguredMoqCustomization (доступно с версии 3.20.0) соответствовало бы вашим требованиям.   -  person dcastro    schedule 21.08.2014


Ответы (2)


Вы пытаетесь провести здесь функциональное тестирование, поэтому было бы разумно иметь функциональную базу данных.

EF может воссоздать и уничтожить вашу базу данных в ваших методах настройки и демонтажа с помощью тестовой строки подключения. Это обеспечит реальную функциональную среду тестирования, в которой ваши тесты будут работать против имитации реальной среды.

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();
            }
        }
person C Bauer    schedule 10.10.2014

Да, это именно то, для чего он предназначен. См. пример ниже. Я использую Mock вместо NSubstitute, потому что не знаком с NSubstitute. Вам просто нужно пройти другую настройку и использовать синтаксис NSubstitute в настройках.

[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
}

Прелесть AutoFixture в том, что вам не нужно создавать макеты для всех зависимостей тестируемой системы. Если вы тестируете функциональность, использующую только одну зависимость, вы просто замораживаете ее перед созданием тестируемой системы. Остальные зависимости будут имитированы автоматически.

person Andrzej Gis    schedule 26.07.2014