Magnus Johansson
Magnus Johansson

Reputation: 28325

How can I mock a method that returns a Task<IList<>>?

I am trying to unit test a method that returns a 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; }
}

But the Task returning method generates a compiler error:

CS1503 Argument 1: cannot convert from 'System.Threading.Tasks.Task<System.Collections.Generic.List<UserQuery.MyModel>' to 'System.Threading.Tasks.Task<System.Collections.Generic.IList<UserQuery.MyModel>'

What am I doing wrong?

Upvotes: 17

Views: 7393

Answers (5)

Ufuk Hacıoğulları
Ufuk Hacıoğulları

Reputation: 38468

You can use ReturnsAync method:

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

Upvotes: 22

gilmishal
gilmishal

Reputation: 1982

Well your problem is that your method should be returning Task<IList> and You are returning Task<List> you can't do that - they are of different types and they do not support contravariance or covariance. You need to cast your return type

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

Upvotes: 0

Magnus Johansson
Magnus Johansson

Reputation: 28325

Posted to soon, found out that Moq has the ReturnsAsync method.

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

Works fine.

Upvotes: 3

SynerCoder
SynerCoder

Reputation: 12766

Cast the result to IList

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

Upvotes: 0

Rico Suter
Rico Suter

Reputation: 11858

Just cast your list to IList:

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

Or define the generic param:

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

Upvotes: 0

Related Questions