2016-04-22 44 views
1

我試圖用起訂量來模擬一個Func<Tin, Tout>並驗證它被調用(引用)無法驗證Moq'd func被調用

我目前擁有的代碼是:

var handlers = new List<ICallBridgeHandler>(); 
var stationIdReader = new Mock<IStationIdReader>(); 
var loggerCreator = new Mock<Func<Type, ILogger>>(); 
loggerCreator.Setup(x => x.Invoke(typeof(Service))).Returns<ILogger>(null); 

loggerCreator.Verify(x => x.Invoke(It.IsAny<Type>()), Times.Never); 
var sut = new Service(stationIdReader.Object, handlers, loggerCreator.Object); 
loggerCreator.Verify(x => x.Invoke(typeof(Service)), Times.Once); 
Assert.IsNotNull(sut); 

但這是吹了除了:

Result StackTrace: 
at Moq.ExpressionExtensions.GetCallInfo(LambdaExpression expression, Mock mock) 
at Moq.Mock.<>c__DisplayClass1c`2.<Setup>b__1b() 
at Moq.PexProtector.Invoke[T](Func`1 function) 
at Moq.Mock.Setup[T,TResult](Mock`1 mock, Expression`1 expression, Condition condition) 
at Moq.Mock`1.Setup[TResult](Expression`1 expression) 
at Tests.ConstructorRetrievesLoggerFromCreator() in ... 

Result Message: 
Test method Tests.ConstructorRetrievesLoggerFromCreator threw exception: 
System.InvalidCastException: Unable to cast object of type 
'System.Linq.Expressions.InstanceMethodCallExpressionN' to type 
'System.Linq.Expressions.InvocationExpression'. 

任何人都可以幫助,我需要能夠檢查構造函數調用Func。

N.B.我試圖刪除設置步驟,因爲我不關心此測試的返回值,並且我在驗證呼叫中遇到同樣的問題。

很顯然,我可以注入返回給定值的具體的FUNC鍵,以某種方式查詢該值,但是我的服務類的樣子:

public class Service 
{ 
    private readonly ILogger _logger; 

    [ImportingConstructor] 
    public Service([Import("GetLogger")]Func<Type, ILogger> loggerCreator) 
    { 
     if (loggerCreator == null) 
      throw new ArgumentNullException(nameof(loggerCreator)); 

     _logger = loggerCreator.Invoke(GetType()); 
    } 
} 

因此,沒有改變我的課,我不能看到成員變量_logger所以我無法驗證loggerCreator已被調用,這就是我想驗證的。

+0

我不知道你能MOQ代表。 – Nkosi

+0

另一個問題沒有說明如何驗證Func是否被調用,它允許你注入一個返回一個模擬對象的Func,通過詢問這個返回的值可以隱式地驗證Func被調用,但是(正如我編輯),因爲我不從我的服務類公開Func的返回值我不能用這種方法修改我的代碼。 – MikeW

回答

1

沒有必要模擬該功能。創建一個Func變量並在其中保留一個計數器以保持跟蹤。

[TestMethod] 
public void Func_Should_Be_Invoked_Once() { 
    //Arrange 
    var handlers = new List<ICallBridgeHandler>(); 
    var stationIdReader = new Mock<IStationIdReader>(); 
    var mockLogger = new Mock<ILogger>(); 
    int loggerCreaterInvokeCalls = 0; 
    Func<Type, ILogger> loggerCreator = (type) => { 
     loggerCreaterInvokeCalls++; 
     return mockLogger.Object; 
    }; 
    //Act 
    var sut = new Service(stationIdReader.Object, handlers, loggerCreator); 
    //Assert 
    Assert.IsNotNull(sut); 
    Assert.AreEqual(1, loggerCreaterInvokeCalls); 
} 

參考:Using Moq to Mock a Func<> constructor parameter and Verify it was called twice

+0

很好的回答Moq是無關緊要的,手動構建的間諜是最好的選擇,謝謝@NKosi – MikeW

+0

@MikeW,沒問題。你注入了一個具體的'Func',並且最終會得到正確的解決方案。 – Nkosi