代码之家  ›  专栏  ›  技术社区  ›  gkb

基于Moq的EF动态投影失败试验

  •  0
  • gkb  · 技术社区  · 7 年前

    我正在为我的服务编写单元测试,它使用实体框架作为ORM与数据库通信。在我的服务中,有一段代码根据表动态投影以选择匿名类型对象,如下所示-

    string selectQuery = "new ( " + string.Join(",", someColumns) + ")";
    var values = await context.MyTable.Where(data => data.Id == someId).Select(selectQuery).ToListAsync();
    

    这是因为我投影的列在编译时是未知的,并且在某些条件下可能会有所不同。使用上面的代码,生产代码按预期工作。

    但是,它开始抛出 System.ArgumentException 当我运行我的测试时-

    '类型的表达式'系统.集合.通用.IEnumerable“1[DynamicClass1]”不能用于返回类型'系统.集合.通用.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 回复  |  直到 7 年前