异步方法返回null

Sim*_* V. 19 c# moq mocking async-await

如果我尝试模拟包含如下async方法的类型:

interface Foo
{
    Task<int> Bar();
}
Run Code Online (Sandbox Code Playgroud)

然后mock的Bar方法返回null.我猜Moq正在选择default(Task<int>)我的方法的默认返回值,这确实是null.然而,Moq应该选择像Task.FromResult(default(int))默认值这样的东西.我可以强制Moq使异步方法返回非空任务吗?

Sim*_* V. 33

如果有人感兴趣,我创建了一个扩展类,使异步方法更简洁:

public static class SetupExtensions
{
    public static IReturnsResult<TMock> ReturnsTask<TMock, TResult>(
        this ISetup<TMock, Task<TResult>> setup) where TMock : class
    {
        return setup.Returns(() => Task.FromResult(default(TResult)));
    }

    public static IReturnsResult<TMock> ReturnsTask<TMock, TResult>(
        this ISetup<TMock, Task<TResult>> setup, TResult value) where TMock : class
    {
        return setup.Returns(() => Task.FromResult(value));
    }

    public static IReturnsResult<TMock> ReturnsTask<TMock, TResult>(
        this ISetup<TMock, Task<TResult>> setup, Func<TResult> func) where TMock : class
    {
        return setup.Returns(Task.Factory.StartNew(func));
    }

    public static IReturnsResult<TMock> ReturnsTask<TMock, T, TResult>(
        this ISetup<TMock, Task<TResult>> setup, Func<T, TResult> func) where TMock : class
    {
        return setup.Returns<T>(arg => Task.Factory.StartNew(() => func(arg)));
    }

    public static IReturnsResult<TMock> ReturnsTask<TMock, T1, T2, TResult>(
        this ISetup<TMock, Task<TResult>> setup, Func<T1, T2, TResult> func) where TMock : class
    {
        return setup.Returns<T1, T2>((arg1, arg2) => Task.Factory.StartNew(() => func(arg1, arg2)));
    }

    public static IReturnsResult<TMock> ReturnsTask<TMock, T1, T2, T3, TResult>(
        this ISetup<TMock, Task<TResult>> setup, Func<T1, T2, T3, TResult> func) where TMock : class
    {
        return setup.Returns<T1, T2, T3>((arg1, arg2, arg3) => Task.Factory.StartNew(() => func(arg1, arg2, arg3)));
    }

    public static IReturnsResult<TMock> ReturnsTask<TMock, T1, T2, T3, T4, TResult>(
        this ISetup<TMock, Task<TResult>> setup, Func<T1, T2, T3, T4, TResult> func) where TMock : class
    {
        return setup.Returns<T1, T2, T3, T4>((arg1, arg2, arg3, arg4) => Task.Factory.StartNew(() => func(arg1, arg2, arg3, arg4)));
    }

    public static IReturnsResult<TMock> ReturnsTask<TMock>(this ISetup<TMock, Task> setup, Action action) where TMock : class
    {            
        return setup.Returns(Task.Factory.StartNew(action));
    }

    public static IReturnsResult<TMock> ReturnsTask<TMock, T>(this ISetup<TMock, Task> setup, Action<T> action) where TMock : class
    {            
        return setup.Returns<T>(arg => Task.Factory.StartNew(() => action(arg)));
    }

    public static IReturnsResult<TMock> ReturnsTask<TMock, T1, T2>(this ISetup<TMock, Task> setup, Action<T1, T2> action) where TMock : class
    {            
        return setup.Returns<T1, T2>((arg1, arg2) => Task.Factory.StartNew(() => action(arg1, arg2)));
    }

    public static IReturnsResult<TMock> ReturnsTask<TMock, T1, T2, T3>(this ISetup<TMock, Task> setup, Action<T1, T2, T3> action) where TMock : class
    {            
        return setup.Returns<T1, T2, T3>((arg1, arg2, arg3) => Task.Factory.StartNew(() => action(arg1, arg2, arg3)));
    }

    public static IReturnsResult<TMock> ReturnsTask<TMock, T1, T2, T3, T4>(this ISetup<TMock, Task> setup, Action<T1, T2, T3, T4> action) where TMock : class
    {            
        return setup.Returns<T1, T2, T3, T4>((arg1, arg2, arg3, arg4) => Task.Factory.StartNew(() => action(arg1, arg2, arg3, arg4)));
    }

    public static IReturnsResult<TMock> ReturnsTask<TMock>(this ISetup<TMock, Task> setup) where TMock : class
    {
        return setup.Returns(Task.Factory.StartNew(delegate {  }));
    }
}
Run Code Online (Sandbox Code Playgroud)

一些例子 :

//Example 1 :
public interface IFoo
{
    Task Bar();
}

var mock = new Mock<IFoo>();

mock.Setup(m => m.Bar()).ReturnsTask(); //await Bar() will return void

//Example 2 :
public interface IFoo
{
    Task<int> Bar();
}

var mock = new Mock<IFoo>();

mock.Setup(m => m.Bar()).ReturnsTask(); //await Bar() will return default(int)

//Example 3 :
public interface IFoo
{
    Task<int> Bar();
}

var mock = new Mock<IFoo>();

mock.Setup(m => m.Bar()).ReturnsTask(4); //await Bar() will return 4;

//Example 4 :
public interface IFoo
{
    Task<int> Bar(int x, int y);
}

var mock = new Mock<IFoo>();

mock.Setup(m => m.Bar(It.IsAny<int>(), It.IsAny<int>()))
                     .ReturnsTask<IFoo, int, int, int>((x,y) => x + y); //await Bar(x, y) will return x + y;
Run Code Online (Sandbox Code Playgroud)


aqu*_*aga 6

您只需要存根Bar方法,然后返回 Task.FromResult(default(int))