Luffy1
@Luffy1
Student, Junior .NET programmer, C#, JS, HTML/CSS

Как заставить объект Moq возвращать разные значения при повторных прогонах теста?

Я пытаюсь разрабатывать WPF-приложение через TDD подход. У меня есть класс, метод которой возвращает входное значение для тестируемого метода и ожидаемый результат:
public class RatingRecordRepositoryTestData
{
    private static void AddRecordToList(List<RatingRecord> list, int index)
    {
        var record = new RatingRecord
        {
            GameCompletionDate = DateOnly.FromDateTime(DateTime.Now)
        };
        list.Add(record);
    }

    public static IEnumerable<object[]> GetAllMethod_TestData()
    {
        var ratingRecordsOnEasyLevel = new List<RatingRecord>();
        var ratingRecordsOnNormalLevel = new List<RatingRecord>();
        var ratingRecordsOnHardLevel = new List<RatingRecord>();

        ratingRecordsOnEasyLevel.Add(new RatingRecord() { GameCompletionTime = new TimeOnly(13, 45, 23), GameCompletionDate = DateOnly.FromDateTime(DateTime.Now) });
        ratingRecordsOnNormalLevel.Add(new RatingRecord() { GameCompletionTime = new TimeOnly(1, 59, 59), GameCompletionDate = DateOnly.FromDateTime(DateTime.Now) });
        ratingRecordsOnHardLevel.Add(new RatingRecord() { GameCompletionTime = new TimeOnly(21, 31, 2), GameCompletionDate = DateOnly.FromDateTime(DateTime.Now) });

        var allData = new List<object[]>
        {
            new object[] { DifficultyLevels.Easy, ratingRecordsOnEasyLevel },
            new object[] { DifficultyLevels.Normal, ratingRecordsOnNormalLevel },
            new object[] { DifficultyLevels.Hard, ratingRecordsOnHardLevel }
        };

        return allData;
    }
}


Вот класс для тестов:
public class RatingRecordRepositoryTests
{
    private Mock<IReadAllRepository<RatingRecord, DifficultyLevels>> _ratingRecordRepositoryMock;

    public RatingRecordRepositoryTests()
    {
        _ratingRecordRepositoryMock = new Mock<IReadAllRepository<RatingRecord, DifficultyLevels>>();
    }

    [Theory]
    [MemberData(nameof(RatingRecordRepositoryTestData.GetAllMethod_TestData), MemberType = typeof(RatingRecordRepositoryTestData))]
    public void Should_ReturnConcreteRatingRecords_When_ConveyingConcreteDifficulty
        (DifficultyLevels difficultyLevel, List<RatingRecord> expectedData)
    {
        _ratingRecordRepositoryMock.SetupSequence(obj => obj.GetAll(difficultyLevel)).Returns(
            new List<RatingRecord> { new RatingRecord() { GameCompletionTime = new TimeOnly(13, 45, 23), GameCompletionDate = DateOnly.FromDateTime(DateTime.Now) } }
            ).Returns(
            new List<RatingRecord> { new RatingRecord() { GameCompletionTime = new TimeOnly(1, 59, 59), GameCompletionDate = DateOnly.FromDateTime(DateTime.Now) } }
            ).Returns(
            new List<RatingRecord> { new RatingRecord() { GameCompletionTime = new TimeOnly(21, 31, 2), GameCompletionDate = DateOnly.FromDateTime(DateTime.Now) } }
            );
        var realObject = _ratingRecordRepositoryMock.Object;

        var actualData = realObject.GetAll(difficultyLevel);

        Assert.Equal(expectedData, actualData);
    }
}

Так как у меня через Theory передаётся три набора данных, то тест будет прогнано три раза. При этом в Moq-объекте я задал, чтобы поочерёдно при каждом прогоне возвращались новые данные. Но в итоге почему-то вернулась только первая коллекция из первого Return:
66e700ecb30e5490226599.png

Я читал тут: https://myadventuresincoding.wordpress.com/2014/02...

Что якобы надо использовать метод GetNextStuff, но его у меня просто нету....

Использую я nuget-пакет Moq от Daniel Cazzulino.

У меня есть ещё идея написать три разных теста для трёх разных сложностей, но мне кажется, что в этом нет необходимости.

Тестируется, если что, вот этот вот интерфейс:

public interface IReadAllRepository<T, F>
{
    void Add(T entity, F key);
    IEnumerable<T> GetAll(F key);
}


Подскажите, пожалуйста, в чём может быть проблема?
  • Вопрос задан
  • 60 просмотров
Пригласить эксперта
Ответы на вопрос 1
@mvv-rus
Настоящий админ AD и ненастоящий программист
Есть подозрение, что при каждом вызове тестового метода с новым параметром экземпляр вашего тестового класса каждый раз создается заново, вместе с новым экземпляром имитатора (Mock> _ratingRecordRepositoryMock; ) . В пользу этого говорит и то, что вы при каждом вызове заново настраиваете имитатор заново, а если бы экземпляр имитатора уже использовался, вы бы получили ошибку.

Проверить просто: поставьте точку остановки (или воткните отладочное сообщение) в конструктор тестового класса.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы