Как проверить добавить метод с Moq в C # - PullRequest
0 голосов
/ 11 июня 2018

Я пытаюсь написать модульный тест для метода Add из класса репозитория.Я использую EF6 и Moq.Мой тестовый метод выглядел так:

public static Mock<DbSet<T>> CreateDbSetMock<T>(IEnumerable<T> elements) where T : class
{
    var elementsAsQueryable = elements.AsQueryable();
    var dbSetMock = new Mock<DbSet<T>>();

    dbSetMock.As<IQueryable<T>>().Setup(m => m.Provider).Returns(elementsAsQueryable.Provider);
    dbSetMock.As<IQueryable<T>>().Setup(m => m.Expression).Returns(elementsAsQueryable.Expression);
    dbSetMock.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(elementsAsQueryable.ElementType);
    dbSetMock.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(elementsAsQueryable.GetEnumerator());

    return dbSetMock;
}

    [Test()]
    public void AddTest()
    {
        // Arrange
        Mock<DbSet<Tytul>> titlesMock = CreateDbSetMock(new List<Tytul>());
        Mock<OzinDbContext> titlesContextMock = new Mock<OzinDbContext>();
        titlesContextMock.Setup(x => x.Tytuly).Returns(titlesMock.Object);
        titlesMock.Setup(x => x.Add(It.IsAny<Tytul>())).Returns((Tytul t) => t);
        IRepository<Tytul> tytulRepository = TytulRepository(titlesContextMock.Object);

        Tytul tytul = new Tytul
        {
            Identyfikator = "ABC"               
        };

        // Act
        tytulRepository.Add(tytul);
             // in Add method:
             //dbContext.Tytuly.Add(entity);
             //dbContext.SaveChanges();
        Tytul tytulInDb = tytulRepository.GetDetail(t => t.Identyfikator == "ABC");
             // in GetDetail method:
             // return dbContext.Tytuly.FirstOrDefault(predicate);
        // Assert
        Assert.AreEqual(tytulInDb.Identyfikator, tytul.Identyfikator);
    }

Моя проблема в том, что метод GetDetail возвращает ноль, но я ожидал, что объект tytulInDb.Что случилось?Как правильно написать этот тест?

1 Ответ

0 голосов
/ 11 июня 2018

Извлеките поддельный источник данных для DbSet в локальную переменную, чтобы с ним можно было взаимодействовать позже в настройках теста.Добавьте Callback в настройку Add, чтобы добавить переданный аргумент в источник данных, чтобы при вызове имитировались фактические данные, на которые будет воздействовать макет.

// Arrange
var data = new List<Tytul>(); //<<< local variable
Mock<DbSet<Tytul>> titlesMock = CreateDbSetMock(data);
var titlesContextMock = new Mock<OzinDbContext>();
titlesContextMock.Setup(x => x.Tytuly).Returns(titlesMock.Object);
titlesMock
    .Setup(x => x.Add(It.IsAny<Tytul>()))
    .Returns((Tytul t) => t)
    .Callback((Tytul t) => data.Add(t)); //<<< for when mocked Add is called.
IRepository<Tytul> tytulRepository = TytulRepository(titlesContextMock.Object);

//...Code removed for brevity

Также при настройкеDbSet Mock использует делегат для Returns, чтобы разрешить множественные перечисления, так как возвращение только значения позволит только один проход перечислителя только для пересылки.

dbSetMock.As<IQueryable<T>>()
    .Setup(m => m.GetEnumerator())
    .Returns(() => elementsAsQueryable.GetEnumerator()); //<<< note delegate
...