2014-01-23 5 views
8

Lasst uns sagen, dass ich IService Schnittstelle haben:Mocking Delegate.Invoke() mit Moq wirft InvalidCast Ausnahme in LINQ

public interface IService 
{ 
    string Name { get; set; } 
} 

Und einen Delegierten Func<IService>, die diese Schnittstelle zurückgibt.

In meiner Unit-Test möchte ich die Delegierten Invoke() Methode Moq wie diese verspotten:

[TestMethod] 
public void UnitTest() 
{ 
    var mockService = new Mock<IService>(); 

    var mockDelegate = new Mock<Func<IService>>(); 
    mockDelegate.Setup(x => x.Invoke()).Returns(mockService.Object); 

    // The rest of the test 
} 

mockDelegate.Setup(...) wirft System.InvalidCastException Leider:

Prüfnorm Unittest Ausnahme ausgelöst hat:

System.InvalidCastException: Das Objekt des Typs 'System.Linq.Expressions.InstanceMethodCallExpre' konnte nicht umgewandelt werden ssionN 'zu Typ' System.Linq.Expressions.InvocationExpression '.

bei Moq.ExpressionExtensions.GetCallInfo (Lambda Ausdruck, Mock mock)

bei Moq.Mock. <> c_ DisplayClass1c`2.b _1b()

bei Moq.PexProtector.Invoke (Func`1 Funktion)

bei Moq.Mock.Setup (Mock 1 mock, Expression 1-Expression, Zustand Zustand)

bei Moq.Mock 1.Setup(Expression 1 expression)

bei Unittest() in UnitTests.cs: Zeile 38

Linie 38 ist mockDelegate.Setup(x => x.Invoke()).Returns(mockService.Object);

Fehle ich etwas? Oder ist es keine gute Idee, den Aufruf von Delegierten zu verspotten?

Vielen Dank.

+3

Es gibt keinen Grund, das zu tun. Mach einfach einen Delegierten. – SLaks

+0

Danke! Immer noch interessant, warum es eine Ausnahme gibt ... –

+1

@NikolaiSamteladze Die Ausnahme ist da, weil dieses Szenario nicht von Moq unterstützt wird, aber anstelle des Auslösens einer NotSupportException erhalten Sie diese nicht so nette InvalidCastException. Welches ist ein Fehler in meinem Opion, so dass der Ausnahmetyp hier behoben werden sollte ... aber Sie sollten den Delegierten nicht nur verspotten, nur schreiben: 'Func mockDelegate =() => mockService.Object;' – nemesv

Antwort

20

Es ist 100% möglich, dies in Moq zu tun, hier ist, wie:

var mockService = new Mock<IService>(); 

var mockDelegate = new Mock<Func<IService>>(); 
mockDelegate.Setup(x => x()).Returns(mockService.Object); 

Der Grund, warum Sie waren immer die InvalidCastException war, weil Sie eine Mock<T> eines Delegattyp erstellen. Somit wird erwartet, dass der Expression vom Typ InvocationExpression (x()) statt InstanceMethodCallExpressionN (x.Invoke()) ist.

Dies ermöglicht Ihnen auch, Aufrufe Ihrer Mock Vertreter, z.

mockDelegate.Verify(x => x(), Times.Once); 

Ich habe dies als eine Antwort geschrieben, denn während es nicht für diese Situation notwendig sein kann, ist es sicherlich sinnvoll sein kann, zu wissen.

+0

Danke! Werde es definitiv heute versuchen. –

1

Diese Antwort ist eine Zusammenfassung von SLaks und nemesv Kommentare.

Es gibt keinen Grund, in erster Linie Func<IService>delegate zu verspotten. Stattdessen kann man schreiben:

[TestMethod] 
public void UnitTest() 
{ 
    var mockService = new Mock<IService>(); 

    Func<IService> mockDelegate =() => mockService.Object; 

    // The rest of the test 
} 

Die Ausnahme ist da, weil dieses Szenario nicht von Moq unterstützt wird. Aber anstatt einen NotSupportException zu werfen, bekommst du nicht so schön InvalidCastException.

+0

Wie in meiner Antwort gezeigt, wird dies von Moq unterstützt, die 'InvalidCastException' ist, weil das Feature falsch verwendet wird. – Lukazoid