Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to return passed parameters in an async method with Moq in unit tests?

I am struggling with the problem of how to use the Moq-Setup-Return construct.

First, my setting:

Some repository of type IRepository-Interface has to implement the StoreAsync-Method that returns a StoreResult object with the stored entity as property included.

using System.Threading.Tasks;
using Moq;
using Xunit;

namespace Tests
{
    public class Entity { }

    public class StoreResult
    {
        public Entity Entity { get; set; }
    }

    public interface IRepository
    {
        Task<StoreResult> StoreAsync(Entity entity);
    }

    public class Tests
    {
        [Fact]
        public void Test()
        {
            var moq = new Mock<IRepository>();
            moq.Setup(m => m.StoreAsync(It.IsAny<Entity>())).Returns(e => Task.FromResult<Task<StoreResult>>(new StoreResult {Entity = e}));
        }
    }
}

Now I try to write a Mock-Objekt for the IRepository-Interface, but I do not know how to code the Return-Statement so that the StoreResult-Object includes the entity given as a parameter to the StoreAsync-Function.

I read about this topic in Moq ReturnsAsync() with parameters and Returning value that was passed into a method.

I have tried

moq.Setup(m => m.StoreAsync(It.IsAny<Entity>()))
     .ReturnsAsync(entity => new StoreResult {Entity = entity});

with the error statement "Cannot convert lambda expression to type "StoreResult", because it is not a delegate type.

And with the same error message I tried

moq.Setup(m => m.StoreAsync(It.IsAny<Entity>()))
     .Returns(e => Task.FromResult<Task<StoreResult>>(new StoreResult {Entity = e}));

I am using a .NET Core xUnit environment with Moq 4.6.36-alpha

Thank you for your help.

like image 675
Ralf Bönning Avatar asked Aug 01 '16 09:08

Ralf Bönning


People also ask

Can async methods declare out parameters?

The only way to have supported out-by-reference parameters would be if the async feature were done by a low-level CLR rewrite instead of a compiler-rewrite.

Can unit tests be async?

Async unit tests that return Task have none of the problems of async unit tests that return void. Async unit tests that return Task enjoy wide support from almost all unit test frameworks.

What is async return method?

Async functions always return a promise. If the return value of an async function is not explicitly a promise, it will be implicitly wrapped in a promise. Note: Even though the return value of an async function behaves as if it's wrapped in a Promise.resolve , they are not equivalent.


1 Answers

Thanks to the tip from Callum Linigton I came to the following solution:

moq
 .Setup(m => m.StoreAsync(It.IsAny<Entity>()))
 .Returns((Entity e) => Task.FromResult(new StoreResult {Entity = e}));

The key difference is to specify the type for the input parameter of the lambda expression in order to avoid ambiguous calls.

like image 78
Ralf Bönning Avatar answered Oct 31 '22 14:10

Ralf Bönning