Я пишу модульные тесты для своего сервиса, который общается с базой данных, используя Entity Framework в качестве ORM. В моем сервисе есть фрагмент кода, который динамически проецируется на таблицу для выбора объекта анонимного типа, как показано ниже -
string selectQuery = "new ( " + string.Join(",", someColumns) + ")";
var values = await context.MyTable.Where(data => data.Id == someId).Select(selectQuery).ToListAsync();
Это так, потому что проецируемые мной столбцы неизвестны во время компиляции и могут изменяться при определенных условиях. Рабочий код работает, как и ожидалось, используя код выше.
Однако при запуске теста он начинает выдавать System.ArgumentException
со следующим сообщением -
Выражение типа 'System.Collections.Generic.IEnumerable & # x60; 1 [DynamicClass1]' нельзя использовать для типа возвращаемого значения 'System.Collections.Generic.IEnumerable & # x60; 1 [MyTable]'
Ниже приведен мой тест -
var values = new List<MyTable>
{
new MyTable
{
Id = 1,
Column1 = value1,
Column2 = value2,
Column3 = value3,
Column4 = value4
},
new MyTable
{
Id = 2,
Column1 = value5,
Column2 = value6,
Column3 = value7,
Column4 = value8
}
}.AsQueryable();
var mockValues = new Mock<DbSet<MyTable>>();
mockValues.As<IDbAsyncEnumerable<T>>()
.Setup(m => m.GetAsyncEnumerator())
.Returns(new TestDbAsyncEnumerator<T>(values.GetEnumerator()));
mockValues.As<IQueryable<T>>().Setup(m => m.Provider).Returns(new TestDbAsyncQueryProvider<T>(values.Provider));
mockValues.As<IQueryable<T>>().Setup(m => m.Expression).Returns(values.Expression);
mockValues.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(values.ElementType);
mockValues.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(values.GetEnumerator());
Mock<Context> contextMock = new Mock<Context>();
contextMock.Setup(x => x.MyTable).Returns(mockValues.Object);
var result = await _myService.SomeMethod(contextMock.Object, ...);
Assert.IsTrue(result);
Я сослался на Документацию Microsoft для поддержки async
для моего теста.
Глядя на исключение, я догадался, что это должно быть связано с динамической проекцией, которую я здесь использую, поэтому я изменил код в сервисе на ниже -
var values = await context.MyTable.Where(data => data.Id == someId).Select(x => new { x.Id, x.Column1, x.Column2, x.Column4 }).ToListAsync();
, который в основном удаляет динамическую конструкцию и, как я ожидал, сработал.
Итак, вопрос в том, есть ли способ динамически проецировать столбцы и при этом работать мои тесты.