Модульные тесты для метода, который использует GetEntitiesAync (DocumentDB) - PullRequest
0 голосов
/ 26 мая 2018

После пересмешивания класса DocumentDBRepository с его методом GetEntitiesAsync() в модульном тесте возвращается значение null, которое, как я ожидаю, не вернется.

Вот мой метод, который мне нужно проверить

 public async Task<Books> GetBooksByBookIdAsyncByLinq(string bookId)
    {

        var books = await _individualRepository.GetEntitiesAsync(t => t.BookID == bookId);

        if (individualResponse.Any())
        {
            return individualResponse.FirstOrDefault();
        }

        return null;
    }

Вот модульный тест этого метода, заметил, что я настроил метод GetEntitiesAsync() и ожидаю, что он вернетбалансовая стоимость .Но он возвращает null, когда я запускаю его:

  [Fact]
        public void Test_GetBooksByBookIdAsyncByLinq()
        {
            //Arrange
            var bookID = "000";

            //Mock DocumentDBRepository
            var mockDocumentDBRepository = new Mock<IRepository<Book>>();
            var expected = Get_BookValue();
            mockDocumentDBRepository.Setup(x => x.GetEntitiesAsync(x => x.BookID == bookID))
                                    .Returns(Task.FromResult(expected));
            var component = new BookComponent(mockDocumentDBRepository.Object);

            //Act
            var result = component.GetBooksByBookIdAsyncByLinq(bookID);
            //Assert
            result.Result.Should().NotBeNull().And.
                 BeOfType<Book>();
        }


        private Book Get_BookValue(){

         IEnumerable<Book> result = new List<Book>
                    { new Book
                    { BookID = "000", BookName = "TestSourceSystemName" } };
                    return result;
        }

Когда я запускаю модульное тестирование и отладку в методе GetBooksByBookIdAsyncByLinq(), он не получает никаких результатов от переменной books и возвратаnull без ошибок.

Интересно то, что когда я меняю метод GetEntitiesAsync() на метод RunSQLQueryAsync(), что означает использование SQL-запроса вместо Linq, модульный тест возвращает правильный результат.

Вот метод, который я тестирую:

public async Task<Books> GetBooksByBookIdAsyncBySQL(string bookId)
        {

            var books = await _individualRepository.RunSQLQueryAsync("select * from c where c.BookID ==" + bookId);

            if (individualResponse.Any())
            {
                return individualResponse.FirstOrDefault();
            }

            return null;
        }

А вот модульный тест для этого метода, заметил, что я настроил метод RunQueryAsync () и ожидаю вернуть книгузначение.И это работает :

        [Fact]
                public void Test_GetBooksByBookIdAsyncBySQL()
                {
                    //Arrange
                    var bookID = "000";

                    var sqlQuery = "select * from c where c.BookID ==" + bookId;

                    //Mock DocumentDBRepository
                    var mockDocumentDBRepository = new Mock<IRepository<Book>>();
                    var expected = Get_BookValue();
//mockDocumentDBRepository.Setup(x => x.GetEntitiesAsync(x => x.BookID == bookID))
//                                        .Returns(Task.FromResult(expected));
                    mockDocumentDBRepository.Setup(x => x.RunQueryAsync(sqlQuery))
                                            .Returns(Task.FromResult(expected));
                    var component = new BookComponent(mockDocumentDBRepository.Object);

                    //Act
                    var result = component.GetBooksByBookIdAsyncBySQL(bookID);
                    //Assert
                    result.Result.Should().NotBeNull().And.
                         BeOfType<Book>();
                }
    private Book Get_BookValue(){

     IEnumerable<Book> result = new List<Book>
                { new Book
                { BookID = "000", BookName = "TestSourceSystemName" } };
                return result;
    }

Так что я думаю, может быть, способ, которым я высмеиваю GetEntitiesAsync() метод неверен .Но я не уверен, почему ...

Вот методы RunQueryAsync() и GetEntitiesAsync() для справки:

public async Task<IEnumerable<T>> GetEntitiesAsync(Expression<Func<T, bool>> predicate)
        {
                IDocumentQuery<T> query = GetQueryByPredicate(predicate);
                List<T> results = new List<T>();
                while (query.HasMoreResults)
                {
                    results.AddRange(await query.ExecuteNextAsync<T>());
                }
                return results;
        }

   public async Task<IEnumerable<T>> RunQueryAsync(string queryString)
        {
            IDocumentQuery<T> query = GetQueryBySQL(queryString);

            List<T> results = new List<T>();

            while (query.HasMoreResults)
            {
                results.AddRange(await query.ExecuteNextAsync<T>());
            }
            return results;
        }

1 Ответ

0 голосов
/ 26 мая 2018

Метод Setup пытается просмотреть аргументы, переданные в ваш метод, и соответствует заданному поведению, только если эти аргументы совпадают.

Когда вы используете GetQueryBySQL, Moq может обнаружить, что строка sqlQuery совпадает (как в object.Equals()) с тем, что было передано, поэтому она работает правильно.

Когда вы используете GetEntitiesAsync, Moq смотрит на два выражения и думает, что они разные, потому что сравнение выражений основано на равенстве памяти.Так что, хотя эти два x => x.BookID == bookID выглядят одинаково для нас с вами, во время выполнения они являются разными выражениями.

Вместо этого попробуйте использовать It.IsAny<>():

mockDocumentDBRepository
    .Setup(x => x.GetEntitiesAsync(It.IsAny<Expression<Func<Book, bool>>()))
    .Returns(Task.FromResult(expected));

Предположим, вы получите этоработая, вы можете использовать Callback или другие стратегии для проверки того, что выражение, переданное в GetEntitiesAsync, имеет ожидаемое поведение.

...