Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to mock a method returning Task<IEnumerable<T>> with Task<List<T>>?

I'm attempting to set up a unit test initializer (in Moq) where an interface method is being mocked:

public interface IRepository
{
    Task<IEnumerable<myCustomObject>> GetSomethingAsync(string someStringParam);
}

...

[TestInitialize]
public void Initialize()
{
    var repoMock = new Mock<IRepository>();

    var objectsList = new List<myCustomObject>() {
        new myCustomObject("Something"), 
        new myCustomObject("Otherthing")
    }

    repoMock.Setup<Task<IEnumerable<myCustomObject>>>(
        rep => rep.GetSomethingAsync("ThisParam")
    ).Returns(Task.FromResult(objectsList)); //error here
}

The issue I'm having is I can't figure out how to get the method to return my objectsList. In practice this of course works fine because List implements IEnumerable, but it doesn't seem to work when wrapped in a Task, in Moq. The error I get is on the Returns() method:

Argument 1: cannot convert from 'System.Threading.Tasks.Task<
  System.Collections.Generic.List<myCustomObject>>'
to 'System.Threading.Tasks.Task<
  System.Collections.Generic.IEnumerable<myCustomObject>>'

As a workaround I can create another method that simply creates the List<myObj> and returns it as IEnumerable<myObj>, but I feel like there must be another way to handle this that is cleaner.

So, how would I do this without having to create the helper method?

like image 703
squid808 Avatar asked May 25 '16 13:05

squid808


People also ask

How do you mock a method in C#?

Trying to mock a method that is called within another method. // code part public virtual bool hello(string name, int age) { string lastName = GetLastName(); } public virtual string GetLastName() { return "xxx"; } // unit test part Mock<Program> p = new Mock<Program>(); p. Setup(x => x. GetLastName()).

How do you mock a method in MOQ?

First, we instantiate the FakeDbArticleMock class and indicate which setup we want to use for this test. Then, it is necessary to instantiate the repository we want to test and inject the mock instance into it. Finally, we call the method we are testing and assert the results.

What can be mocked with MOQ?

Moq can be used to mock both classes and interfaces.


2 Answers

You need to specify the <IEnumerable<myCustomObject>> on the Task.FromResult, like this:

[TestInitialize]
public void Initialize()
{
    var repoMock = new Mock<IRepository>();

    var objectsList = new List<myCustomObject>() {
        new myCustomObject("Something"), 
        new myCustomObject("Otherthing")
    }

    repoMock.Setup<Task<IEnumerable<myCustomObject>>>(
        rep => rep.GetSomethingAsync("ThisParam")
    ).Returns(Task.FromResult<IEnumerable<myCustomObject>>(objectsList));
}

Alternatively you could declare your objectList as <IEnumerable<myCustomObject>> before assigning it from the List<myCustomObject>. Making the previous suggestion not required.

like image 80
David Pine Avatar answered Oct 09 '22 03:10

David Pine


You could generically cast your original object:

IEnumerable<myCustomObject> objectsList = new List<myCustomObject>() {
    new myCustomObject("Something"), 
    new myCustomObject("Otherthing")
};
like image 44
Brian Mains Avatar answered Oct 09 '22 02:10

Brian Mains