带有Moq的EF动态投影失败测试

时间:2018-09-13 09:40:29

标签: c# entity-framework unit-testing moq mstest

我正在为我的服务编写单元测试,该服务使用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'1 [DynamicClass1]'的表达式不能用于返回类型'System.Collections.Generic.IEnumerable'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 Documentation推荐了async支持我的测试。

通过查看异常,我猜想这应该与我在此处使用的动态投影有关,因此我将服务中的代码更改为以下代码-

var values = await context.MyTable.Where(data => data.Id == someId).Select(x => new { x.Id, x.Column1, x.Column2, x.Column4 }).ToListAsync();

基本上删除了动态结构,并且按我的预期工作了。

所以,问题是-有没有一种方法可以动态地投影列并且仍然可以进行我的测试。

0 个答案:

没有答案