Тестирование с поддельным DbContext, Autofixture и Moq

ТАК следуйте этому примеру

пример и как создать поддельный DBContex. Для проверки моего протестируйте, используя только эту работу

[Test]
public void CiudadIndex()
{
    var ciudades = new FakeDbSet<Ciudad>
    {
        new Ciudad {CiudadId = 1, EmpresaId =1, Descripcion ="Santa Cruz", FechaProceso = DateTime.Now, MarcaBaja = null, UsuarioId = 1},
        new Ciudad {CiudadId = 2, EmpresaId =1, Descripcion ="La Paz", FechaProceso = DateTime.Now, MarcaBaja = null, UsuarioId = 1},
        new Ciudad {CiudadId = 3, EmpresaId =1, Descripcion ="Cochabamba", FechaProceso = DateTime.Now, MarcaBaja = null, UsuarioId = 1}
    };

    //// Create mock unit of work
    var mockData = new Mock<IContext>();
    mockData.Setup(m => m.Ciudades).Returns(ciudades);

    // Setup controller
    var homeController = new CiudadController(mockData.Object);

    // Invoke
    var viewResult = homeController.Index();
    var ciudades_de_la_vista = (IEnumerable<Ciudad>)viewResult.Model;

    // Assert..
}

Сейчас я пытаюсь использовать Autofixture-Moq.

создать "ciudades", но я не могу. я пробую это

var fixture = new Fixture();
var ciudades = fixture.Build<FakeDbSet<Ciudad>>().CreateMany<FakeDbSet<Ciudad>>();
var mockData = new Mock<IContext>();
mockData.Setup(m => m.Ciudades).Returns(ciudades);

я получаю эту ошибку

Не могу преобразовать System.Collections.Generic.IEnumerable(FakeDbSet(Ciudad)) в System.Data.Entity.IDbSet(Ciudad)

не могу поставить "‹>", поэтому я заменяю на "()" в сообщении об ошибке

Реализация IContext и FakeDbSet

public interface IContext
{
    IDbSet<Ciudad> Ciudades { get; }
}
public class FakeDbSet<T> : IDbSet<T> where T : class

как заставить это работать?


person Diego_DX    schedule 22.05.2013    source источник
comment
Какая версия AutoFixture?   -  person Ruben Bartelink    schedule 23.05.2013
comment
@Diego_DB, это означает, что у def не должно быть причин переформулировать аргументы типа в ваших вызовах CreateMany.   -  person Ruben Bartelink    schedule 23.05.2013


Ответы (3)


Небольшой момент... В таких вещах, как:

var ciudades_fixture = fixture.Build<Ciudad>().CreateMany<Ciudad>();

Аргумент второго типа не нужен и должен быть:

var ciudades_fixture = fixture.Build<Ciudad>().CreateMany();

Я действительно понимаю, почему вам нужен FakeDbSet, и статья немного TL; DR ... В общем, я стараюсь избегать подделок и гадостей с битами ORM и вместо этого иметь дело с интерфейсами, возвращающими POCO в максимально возможной степени.

Кроме того... Причина, по которой нормальный синтаксис для инициализации списка работает, заключается в том, что в DBFixture есть AddIEnumerable). В AutoFixture нет истории для этого шаблона напрямую (в конце концов, это синтаксический сахар компилятора, который не особенно поддается отражению или соответствует каким-либо другим соглашениям), но вы можете использовать AddManyTo, пока в игре есть ICollection. К счастью, в реализации FakeDbSet, как и в статье, следующее дает нам вход:

public ObservableCollection<T> Local
{
    get { return _data; }
}

Поскольку ObservableCollection<T> происходит от ICollection<T>, вы должны иметь возможность:

var ciudades = new FakeDbSet<Cuidad>();
fixture.AddManyTo(ciudades.Local);

var mockData = new Mock<IContext>();
mockData.Setup(m => m.Ciudades).Returns(ciudades);

Можно выполнить настройку, чтобы сделать это красивее, но, по крайней мере, у вас есть способ управлять этим. Другой вариант состоит в том, чтобы что-то реализовать ICollection (или добавить свойство с сеттером, принимающим IEnumerable<T>, и заставить AF сгенерировать родительский объект, в результате чего указанная коллекция будет заполнена.


Длинное замененное примечание: в вашем первоначальном вопросе у вас фактически есть:

fixture.Build<FakeDbSet<Ciudad>>().CreateMany()

Тогда проблема становится яснее — вы просите AF сгенерировать много FakeDbSet<Ciudad>s, а это не то, что вам нужно.

person Ruben Bartelink    schedule 22.05.2013
comment
Я стараюсь избегать фальсификации и гадости с битами ORM и вместо этого иметь дело с интерфейсами, возвращающими POCO в максимально возможной степени. у вас есть пример для этого? Я новичок в тесте, издеваюсь, Ди и все это говорит здесь - person Diego_DX; 23.05.2013
comment
@Diego_DX Слишком сильно зависит от того, что ты делаешь. В одном случае мой Контроллер разговаривает с чем-то, что возвращает T[], вместо того, чтобы запихивать что-то в X<T> только для того, чтобы затем повернуться и попросить его обо всем, что я ввел - в общем, я бы сосредоточился на вычислении как одна вещь разговаривает с внешним миром в каждый момент времени. Но это только общие черты. Могу ли я настоятельно рекомендовать два курса Марка Симанна по PluralSight? Например, расширенное модульное тестирование может быть немного натянутым в зависимости от того, с чего вы начинаете, но во всей его работе много понимания (и это не статьи TL; DR!) - person Ruben Bartelink; 23.05.2013

Я не использовал AutoFixture какое-то время, но не должно ли это быть:

var ciudades = new FakeDbSet<Ciudad>();
fixture.AddManyTo(ciudades);
person Sunny Milenov    schedule 22.05.2013

на данный момент я заканчиваю это делать, я буду продолжать читать о том, как использовать automoq, потому что я новичок в этом

var fixture = new Fixture();
var ciudades_fixture = fixture.Build<Ciudad>().CreateMany<Ciudad>();
var ciudades = new FakeDbSet<Ciudad>();
foreach (var item in ciudades_fixture)
{
    ciudades.Add(item);
}
var mockData = new Mock<IContext>(); 
fixture.Create<Mock<IContext>>();
mockData.Setup(r => r.Ciudades).Returns(ciudades);
person Diego_DX    schedule 22.05.2013
comment
AutoMoq просто добавляет сюда больше технического беспорядка - например. fixture.Create<Mock<IContext>>() не имеет никаких побочных эффектов; . AddManyTo - это реальный ответ, но FakeDbSet не позволяет этого напрямую, как обсуждалось в моем ответе. сказав это, функционально он достигает того же, что и строки 2-7 выше, и вы можете довольно легко извлечь это в общий метод расширения. - person Ruben Bartelink; 23.05.2013