2010-05-26 10 views
18

Non riesco a capire come impostare indexers in C# con Moq. La documentazione Moq è debole, e ho fatto un sacco di ricerche ... quello che mi piacerebbe fare è simile nella soluzione per How to Moq Setting an Indexed property:Uso di Moq per impostare gli indicizzatori in C#

var someClass = new Mock<ISomeClass>(); 
someClass.SetupSet(o => o.SomeIndexedProperty[3] = 25); 

voglio modificare il precedente per funzionare per qualsiasi indice e qualsiasi valore così posso solo fare qualcosa di simile:

someClass.Object.SomeIndexedProperty[1] = 5; 

Attualmente ho il seguente, che funziona alla grande per il getter proprietà indicizzata, ma se mai impostato il valore Moq lo ignora:

var someValues = new int[] { 10, 20, 30, 40 }; 
var someClass = new Mock<ISomeClass>(); 
someClass.Setup(o => o.SomeIndexedProperty[It.IsAny<int>()]) 
    .Returns<int>(index => someValues[index]); 

// Moq doesn't set the value below, so the Assert fails! 
someClass.Object.SomeIndexedProperty[3] = 25; 
Assert.AreEqual(25, someClass.Object.SomeIndexedProperty[3]); 
+0

Qual è la variabile dell'indice? da dove viene? – Grzenio

+0

Sono nuovo di Moq quindi forse sto facendo qualcosa di sbagliato ... ma pensavo che il parametro index nel lambda Returns fosse fornito da It.IsAny () espressione nel setup lambda. –

+0

Non sono neanche un esperto (sto usando RhinoMocks). QualcheClass.Object.SomeIndexedProperty [3] restituisce 40? – Grzenio

risposta

11

ho trovato una soluzione al mio problema. Richiede un cambiamento nel mio modo di pensare ... Stavo cercando di usare NUnit's Assert per verificare che il setter dell'indicizzatore nel mio someClass mock venisse chiamato con il valore corretto.

Sembra che con Moq il modo supportato per farlo consiste nell'utilizzare la funzione VerifySet. Un esempio forzato:

prova
someClass.Object.SomeIndexedProperty[3] = 25; 
someClass.VerifySet(mock => mock.SomeIndexedProperty[3] = 25); 

L'unità passa dal SomeIndexedProperty[3] è impostato a 25, ma sarebbe altrimenti sicuro.

+0

Ho lo stesso problema, solo la mia proprietà indicizzata è in sola lettura, cioè ha solo un accesso 'get'. Qualche idea su come posso deridere questo? – MoonKnight

3

Nel tuo test le tue uniche aspettative per il getter dell'indicizzatore - e questo restituirà sempre il valore corrispondente dal tuo array. L'indicizzatore non si comporta come una cosa reale. Puoi provare alcune cose per risolverlo:

  1. È possibile controllare se è possibile eseguire lo stub dell'indicizzatore. Sono personalmente usando RhinoMocks, quindi non ho idea se questo è implementato

    someClass.SetupProperty(f => f.SomeIndexedProperty); 
    
  2. Si può provare a prendere in giro il setter come bene e fare per cambiare la matrice sottostante. La mia prima risposta sarebbe quello di provare qualcosa in questo senso (nessuna garanzia che funzionerà):

    someClass.Setup(o => o.SomeIndexedProperty[It.IsAny<int>()] = It.IsAny<int>()) 
    .Callback((index, value) => someValues[index] = value); 
    
  3. O se l'interfaccia ISomeClass è abbastanza piccolo, si può solo creato un'implementazione stub te stesso (che avrebbe l'indicizzatore implementato come un dizionario, un array ecc)

 

+0

# 1 non ha funzionato nei miei esperimenti. Stavo tentando di fare qualcosa come # 2, ma non ho provato una richiamata. Grazie anche per aver sottolineato # 3 - a volte si finisce per provare a martellare in una vite invece di trovare solo un cacciavite. –

5

Utilizzando Moq 3.1.416.3

installazione non funzionerà per indicizzatori (perché ci vuole un'espressione che significa che le istruzioni di assegnazione sono escluse)

quindi è necessario utilizzare SetupSet come

_settingsStore.SetupSet(store => store["MruNotes"] = It.IsAny<string>()) 
       .Callback<string,string>((key, value) => persistedValue = value); 

Un piccolo avvertimento: questa espressione corrisponde solo se la chiave è "MruNotes". Non ero in grado di utilizzare un matcher come It.IsAny per la chiave.