Модульное тестирование Entity Framework с Mock IDbSet

Я никогда раньше не занимался модульным тестированием, и я споткнулся и споткнулся на своем первом тесте. Проблема в том, что _repository.Golfers.Count(); всегда указывает, что DbSet пусто.

Мой тест прост, я просто пытаюсь добавить нового игрока в гольф

[TestClass]
public class GolferUnitTest //: GolferTestBase
{
    public MockGolfEntities _repository;

    [TestMethod]
    public void ShouldAddNewGolferToRepository()
    {
        _repository = new MockGolfEntities();

        _repository.Golfers = new InMemoryDbSet<Golfer>(CreateFakeGolfers());

        int count = _repository.Golfers.Count();
        _repository.Golfers.Add(_newGolfer);

        Assert.IsTrue(_repository.Golfers.Count() == count + 1);
    }

    private Golfer _newGolfer = new Golfer()
    {
        Index = 8,
        Guid = System.Guid.NewGuid(),
        FirstName = "Jonas",
        LastName = "Persson"
    };
    public static IEnumerable<Golfer> CreateFakeGolfers()
    {
        yield return new Golfer()
        {
            Index = 1,
            FirstName = "Bill",
            LastName = "Clinton",
            Guid = System.Guid.NewGuid()
        };
        yield return new Golfer()
        {
            Index = 2,
            FirstName = "Lee",
            LastName = "Westwood",
            Guid = System.Guid.NewGuid()
        };
        yield return new Golfer()
        {
            Index = 3,
            FirstName = "Justin",
            LastName = "Rose",
            Guid = System.Guid.NewGuid()
        };
    }

Я построил модель данных, используя Entity Framework и сначала код. Я издевался над производным классом для IDbSet, чтобы проверить мой контекст (реверанс людям в сети, которых я точно не помню)

public class InMemoryDbSet<T> : IDbSet<T> where T : class
{
    readonly HashSet<T> _set;
    readonly IQueryable<T> _queryableSet;

    public InMemoryDbSet() : this(Enumerable.Empty<T>()) { }

    public InMemoryDbSet(IEnumerable<T> entities)
    {
        _set = new HashSet<T>();

        foreach (var entity in entities)
        {
            _set.Add(entity);
        }

        _queryableSet = _set.AsQueryable();
    }

    public T Add(T entity)
    {
        _set.Add(entity);
        return entity;

    }

    public int Count(T entity)
    {
        return _set.Count();
    }

    // bunch of other methods that I don't want to burden you with
}

Когда я отлаживаю и прохожу код, я вижу, что я создаю экземпляр _repository и заполняю его тремя поддельными игроками в гольф, но когда я выхожу из функции добавления, _respoistory.Golfers снова пуст. когда я добавляю нового игрока в гольф, запускается _set.Add(entity) и игрок в гольф добавляется, но снова _respoistory.Golfers пуст. Что мне здесь не хватает?

Обновить

Извините за идиотизм, но я не реализовал set в своем MockGolfEntities контексте. Причина, по которой я этого не сделал, заключается в том, что я пытался раньше, но не мог понять, как это сделать, пошел дальше и забыл об этом. Итак, как мне установить IDbSet? Это то, что я пробовал, но это дает мне ошибку переполнения стека. Я чувствую себя идиотом, но не могу понять, как написать функцию set.

public class MockGolfEntities : DbContext, IContext
{
    public MockGolfEntities() {}

    public IDbSet<Golfer> Golfers { 
        get {
            return new InMemoryDbSet<Golfer>();
        }
        set {
            this.Golfers = this.Set<Golfer>();
        }
    }
}

person The Jonas Persson    schedule 03.08.2012    source источник
comment
Метод set вызывает сам себя, присваивая значение this.Golfers. Вы должны где-то хранить значение. Например: this.golfers = value;, где golfers — это личное поле (private IDbSet<Golfer> golfers;).   -  person Sam    schedule 08.07.2013


Ответы (1)


Вам не нужно реализовывать get/set, следующего кода должно быть достаточно, чтобы сгенерировать контекст для вас.

public class MockGolfEntities : DbContext, IContext
{
    public MockGolfEntities() {}

    public IDbSet<Golfer> Golfers { get; set;}

}

Я реализовал код, который у вас был в исходном посте, и у меня все, похоже, работало хорошо — где вы взяли исходный код для InMemoryDbSet? Я использую пакет NuGet 1.3, возможно, стоит попробовать эту версию?

person Mark Oreta    schedule 03.08.2012
comment
Спасибо - я все еще не понимаю, как реализовать набор, если захочу, но я рад оставить магию на усмотрение IDbSet. Я понимаю, что мой набор был безумным, так как я пытаюсь установить свойство в бесконечном цикле, но я был в отчаянии и хотел опубликовать некоторый код, чтобы показать, что я, по крайней мере, попробовал :-). Я не использовал NuGet, но я пытаюсь его использовать. Спасибо за ссылку. - person The Jonas Persson; 03.08.2012