如何模拟返回Task<IList<>>的方法?

17

我正在尝试对返回Task的方法进行单元测试:

void Main()
{
    var mockRepo = new Mock<IRepository>();
    mockRepo.Setup(x => x.GetAll()).Returns(new List<MyModel>() { new MyModel { Name = "Test" } });  // works

    mockRepo.Setup(x => x.GetAllAsync()).Returns(Task.FromResult(new List<MyModel>() { new MyModel { Name = "Test" } }));  // error

    var result = mockRepo.Object.GetAll();
    result.Dump();
}

public interface IRepository
{
    Task<IList<MyModel>> GetAllAsync();
    IList<MyModel> GetAll();
}

public class MyModel
{
    public string Name { get; set; }
}

但是返回任务的方法生成编译错误:

CS1503 参数 1: 无法将类型为“System.Threading.Tasks.Task<System.Collections.Generic.List<UserQuery.MyModel>>” 的对象隐式转换为类型“System.Threading.Tasks.Task<System.Collections.Generic.IList<UserQuery.MyModel>>”

我做错了什么?

5个回答

22

你可以使用ReturnsAsync方法:

IList<MyModel> expected = new List<MyModel>() { new MyModel { Name = "Test" }};
mockRepo.Setup(x => x.GetAll()).ReturnsAsync(expected);

1
谢谢,我刚找到它。 - Magnus Johansson

3

发布得太早了,发现 Moq 有 ReturnsAsync 方法。

mockRepo.Setup(x => x.GetAllAsync()).ReturnsAsync((new List<MyModel>() { new MyModel { Name = "Test" } });  

运行正常。


0

只需将您的列表转换为IList:

Task.FromResult((IList<MyModel>) new List<MyModel>() { new MyModel { Name = "Test" } })

或者定义泛型参数:

Task.FromResult<IList<MyModel>>(new List<MyModel>() { new MyModel { Name = "Test" } })

是的,谢谢,那个可以用。但我找到了一个更优雅的解决方案,使用ReturnsAsync方法。 - Magnus Johansson

0

将结果转换为 IList

Task.FromResult((IList)new List() { new MyModel { Name = "Test" } });

0
你的问题在于你的方法应该返回 Task<IList>,而你返回了 Task<List>。这是不允许的——它们是不同的类型,不支持逆变或协变。你需要强制转换你的返回类型。
 mockRepo.Setup(x => x.GetAllAsync()).Returns(Task.FromResult((IList<MyModel>)new List<MyModel>() { new MyModel { Name = "Test" } }));

不好意思,你的结论是错误的。请再次阅读我的问题。 - Magnus Johansson
我非常确定这不是问题,因为我的答案与其他人完全相同,而且显然有效 - 原因在于泛型的协变和逆变。无论如何,被接受的答案才是正确的。 - gilmishal
不,你的说法:“你的问题在于你的方法应该返回Task<IList>而你返回了Task<List>,你不能这样做”是错误的。这就是我反对的地方。事实上,正如问题中所述,它确实返回了一个IList的Task。 - Magnus Johansson
Task.FromResult(new List<MyModel>() { new MyModel { Name = "Test" } })这段代码在 .Returns() 中返回一个 Task<List> 的值,而不是 Task<IList>。 - gilmishal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接