2011-10-10 23 views
61

Sto usando un lambda con una funzione a più parametri ma Moq lancia questa eccezione in fase di esecuzione quando tento di chiamare la riga mock.Object.Convert(value, null, null, null);.Moq + Unit Testing: System.Reflection.TargetParameterCountException: Parameter count mismatch

System.Reflection.TargetParameterCountException: Parameter count mismatch

Il codice è:

var mock = new Mock<IValueConverter>(); 

mock.Setup(conv => conv.Convert(It.IsAny<Object>(), It.IsAny<Type>(), 
    It.IsAny<Object>(), It.IsAny<CultureInfo>())).Returns((Int32 num) => num + 5); 

var value = 5; 
var expected = 10; 
var actual = mock.Object.Convert(value, null, null, null); 

Qual è il modo corretto per la sua attuazione?

risposta

108

E 'il tuo Returns clausola. Hai un metodo a 4 parametri che stai configurando, ma stai utilizzando solo un parametro lambda. Ho effettuato le seguenti operazioni senza problemi:

[TestMethod] 
public void IValueConverter() 
{ 
    var myStub = new Mock<IValueConverter>(); 
    myStub.Setup(conv => conv.Convert(It.IsAny<object>(), It.IsAny<Type>(), It.IsAny<object>(), It.IsAny<CultureInfo>())). 
     Returns((object one, Type two, object three, CultureInfo four) => (int)one + 5); 

    var value = 5; 
    var expected = 10; 

    var actual = myStub.Object.Convert(value, null, null, null); 

    Assert.AreEqual<int>(expected, (int) actual); 
} 

Nessuna eccezione, test superato.

+0

Stavo per chiedere se si trattava di un test del framework o no, ma ho pensato che avrei avuto il beneficio del dubbio che forse era il codice provvisorio per cercare di convincere il Mock a comportarsi correttamente. –

+0

Suppongo sia troppo, ma mi ha fatto ridere comunque. –

+0

Ti sento. Quando ho eseguito il codice, ho pensato "sì, le librerie di framework funzionano ancora". :) –

2

Forse è perché si sta passando null ma It.IsAny<Object>() si aspetta qualsiasi object tranne null? Che cosa succede se si fa la seguente ?:

var actual = mock.Object.Convert(value, new object(), typeof(object), CultureInfo.CurrentCulture); 

Questo è solo un salto nel buio da me, io sono più familiarità con Rhino.Mocks.


La mia seconda ipotesi:

aver guardato il Moq.chm che viene fornito con il download,

Si utilizza il metodo Setup(Expression<Action<T>>) che "Specifica una configurazione del tipo deriso per una chiamata a un metodo void. "

Si desidera il metodo Setup<TResult>(Expression<Func<T,TResult>>) che "Specifica un'impostazione sul tipo di mocked per una chiamata a un metodo che restituisce un valore".

Quindi si potrebbe provare:

mock.Setup<Int32>(
    conv => { 
     conv.Convert(
      It.IsAny<Object>(), 
      It.IsAny<Type>(), 
      It.IsAny<Object>(), 
      It.IsAny<CultureInfo>()); 
     return num + 5; 
     }); 
+0

mock. Il set deduce il tipo restituito come Oggetto poiché il metodo Convert restituisce un Oggetto. –

4

Non una risposta per OP ma forse per Googler futuri:

ho avuto un Callback che non corrisponde alla firma del metodo di installazione essendo

Mock 
    .Setup(r => r.GetNextCustomerNumber(It.IsAny<int>())) 
    .Returns(AccountCounter++) 
    .Callback<string, int>(badStringParam, leadingDigit => 
    { 
     // Doing stuff here, note that the 'GetNextCustomerNumber' signature is a single int 
     // but the callback unreasonably expects an additional string parameter. 
    }); 

Questo è stato il risultato di qualche refactoring e lo strumento di refactoring ovviamente non poteva rendersi conto che la firma Callback non era corretta

+0

wow, stavo sbattendo la testa contro questo stesso problema e ho continuato a soffermarmi sul callback fino a quando ho letto il tuo post. Molto utile e sono contento che tu l'abbia postato. – dblood

1

Nel mio caso, ho pensato che il tipo in Returns<> fosse il tipo di output, ma in realtà era il tipo di input.

Quindi, se si dispone di un metodo di

public virtual string Foo(int a, int b) { ... } 

La clausola corretta è .Returns<int, int>(...), NON .Returns<string>(...) che è quello che ho pensato inizialmente.

L'errore è stato perché stavo testando inizialmente una funzione con lo stesso tipo di input e di ritorno, ad esempio public virtual string Foo(string a).