gpt4 book ai didi

C# 单元测试异步错误

转载 作者:行者123 更新时间:2023-11-30 21:40:19 28 4
gpt4 key购买 nike

只是为了设置问题,当我来编写单元测试时,我遇到了以下错误:

Error: The source IQueryable doesn't implement IDbAsyncEnumerable

问题发生在测试调用ToListAsync()的方法时,单元测试如下:

[TestMethod]
public async Task Method1CallsCount()
{
//arrange
MockContainer container = new MockContainer();

IQueryable<Entity1DTO> querableentity1DTO = new List<Entity1DTO>().AsQueryable();

container.DefaultQueryFactory.Setup(p => p.Load(It.IsAny<ContextEnums>(), It.IsAny<Expression<Func<Entity1, Entity1DTO>>>(),
It.IsAny<Expression<Func<Entity1, bool>>>(), It.IsAny<int>(), It.IsAny<bool>())).Returns(querableentity1DTO);

var manager = new Manager1(container.DefaultQueryFactory.Object);

//act
var result = await manager.Method1();

//assert
//container.repo1.Verify(x => x.repoMethod(It.IsAny<Expression<Func<Entity1,bool>>>()), Times.Once);
}

这是我正在测试的方法:

public async Task<List<Entity1DTO>> Method1()
{
Expression<Func<Entity1, Entity1DTO>> select = (x => new Entity1DTO()
{
...
});

Expression<Func<Entity1, bool>> where = (x => x.Property == "Test");

return await _defaultQueryFactory.Load(ContextEnums.Enum1, select, where).ToListAsync();

}

为了提供一点帮助,我尝试模拟在查询工厂中加载数据的方法,但出现错误是因为 DTO 模型未实现 IDbAsyncEnumerable,现在正在测试的方法发送了一条选择语句以及查询工厂随后用于生成查询的 where 语句和实体类型,然后在从加载方法返回时使用 ToListAsync() 执行该查询。错误消息显示 DTO 模型是未实现 IDbAsync 的模型,而不是 DB 实体本身。

我知道还有其他一些类似的问题,但我的不同之处在于我使用 DTO 模型并且所讨论的方法不使用上下文本身,因为它被注入(inject)到加载方法中而不是在调用 ToListAsync() 的位置。

有人有什么想法吗?

最佳答案

错误发生是因为 Entity Framework 异步扩展方法不适用于任何 IQueryable - 它还应该实现 IDbAsyncEnumerable 接口(interface)。考虑一下:

var query = new List<EntityDTO>().AsQueryable();
var result = query.ToListAsync().Result;

这将引发您在代码中观察到的相同异常。 AsQueryable 返回的EnumerableQuery 没有实现所需的接口(interface),因此我们需要使用其他实现。我们可以在 this 中找到一个文章(或者自己创造,因为这并不难):

static class TestExtensions {
public static IQueryable<T> AsAsyncQueryable<T>(this IEnumerable<T> source) {
return new TestDbAsyncEnumerable<T>(source);
}
}

internal class TestDbAsyncEnumerable<T> : EnumerableQuery<T>, IDbAsyncEnumerable<T>
{
public TestDbAsyncEnumerable(IEnumerable<T> enumerable)
: base(enumerable)
{ }

public TestDbAsyncEnumerable(Expression expression)
: base(expression)
{ }

public IDbAsyncEnumerator<T> GetAsyncEnumerator()
{
return new TestDbAsyncEnumerator<T>(this.AsEnumerable().GetEnumerator());
}

IDbAsyncEnumerator IDbAsyncEnumerable.GetAsyncEnumerator()
{
return GetAsyncEnumerator();
}
}

internal class TestDbAsyncEnumerator<T> : IDbAsyncEnumerator<T> {
private readonly IEnumerator<T> _inner;

public TestDbAsyncEnumerator(IEnumerator<T> inner) {
_inner = inner;
}

public void Dispose() {
_inner.Dispose();
}

public Task<bool> MoveNextAsync(CancellationToken cancellationToken) {
return Task.FromResult(_inner.MoveNext());
}

public T Current => _inner.Current;

object IDbAsyncEnumerator.Current => Current;
}

现在我们可以做:

IQueryable<Entity1DTO> querableentity1DTO = new List<Entity1DTO>().AsAsyncQueryable();

并且 EF 异步方法将在其上正确执行。

关于C# 单元测试异步错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44718835/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com