2013-05-09 8 views
17

Wenn ich versuche, eine Art zu verspotten eine async Methode enthalten, wie:Async Methoden null zurück

interface Foo 
{ 
    Task<int> Bar(); 
} 

Dann wird die Bar Methode des mock kehrt null. Ich denke, Moq wählt default(Task<int>) als Standard-Rückgabewert für meine Methode, die in der Tat ist null. Moq sollte jedoch eher einen Wert wie Task.FromResult(default(int)) als Standardwert wählen. Kann ich Moq zwingen, asynchrone Methoden zu erstellen, die Nicht-Null-Aufgaben zurückgeben?

Antwort

33

Wenn jemand interessiert ist, habe ich eine Verlängerung Klasse, die Asynchron-Methoden Stübing weniger ausführlich macht:

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 { })); 
    } 
} 

Einige Beispiele:

//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; 
+1

Epicly nützlich. Danke :-) –

+0

Das funktioniert hervorragend – Ian1971

5

Sie müssen nur die Bar Methode Stummel, und es Task.FromResult(default(int))

1

Recall Rückkehr, dass der Moq Rahmen Open Source ist. In der Codebasis (verfügbar here) können wir sehen, dass der Rückgabewert das Ergebnis des valueDel privaten Feldes in der Klasse MethodCallReturn<TMock, TResult> ist, wenn ein Methodenaufruf ausgeführt wird, der nicht eingerichtet worden ist. Das Feld ist so instanziiert, dass es den Standardwert des Ergebnistyp zurück:

private Delegate valueDel = (Func<TResult>)(() => default(TResult)); 

Sie eine Methode hinzufügen könnte, die den Standardwert für einen bestimmten Typ außer Kraft setzen würde, die von einem Mock zurückgegeben wird, oder explizit zurückgeben Ihre vorgeschlagene Standard im Task Fall.

Sie könnten auch ein Problem auf dem Moq issues list page ablegen.

Ohne sich mit der Moq-Quelle zu beschäftigen, müssen Sie jedoch nur die Foo-Schnittstelle stubben, wie von aquaraga vorgeschlagen. Eine kurze Erklärung des Unterschieds zwischen Mocks und Stubs finden Sie unter here.

3

Sieht aus wie dieses Problem fixed in Moq 4.2 ist. Du musst also nur auf die neueste Version von Moq upgraden (zumindest hat es angefangen, in meinem Fall nicht leere Aufgaben zurückzuliefern)