Ho un problema interessante da risolvere. Prendi in considerazione un'interfaccia come questa:Come imitare `object.Equals (object obj)` per un'interfaccia usando Moq
public interface IMyThing
{
int Id { get; }
}
Ora voglio testare il codice che utilizza questa interfaccia. Forse qualcosa con qualche magia LINQ. Qualcosa di simile a questo:
public class SomeClass
{
private IMyThing _thing;
...
public bool HasThing(IEnumerable<IMyThing> things)
{
return things.Contains(_thing);
}
}
sto beffardo tutti gli oggetti attuazione IMyThing
utilizzando Moq
:
public static IMyThing MockMyThing(int newId)
{
var mock = new Mock<IMyThing>();
mock.Setup(s => s.Id).Returns(newId);
mock.Setup(s => s.Equals(It.IsAny<object>())).Returns<object>(obj =>
{
if (typeof(IMyThing).IsAssignableFrom(obj.GetType()))
{
return ((IMyThing)obj).Id == newId;
}
return false;
});
return mock.Object;
}
Ecco la cosa. Il codice sopra riportato viene compilato senza avvisi ma non funzionerà mai. Moq
crea un intercettore per il metodo Equals()
ma non viene mai raggiunto. Invece, viene chiamato il metodo equals del proxy dell'oggetto. Sto dando la colpa al fatto che sto prendendo in giro un'interfaccia ma non una lezione concreta.
UPDATE: Appena realizzato Moq
non crea nemmeno un intercettore.
Naturalmente potrei aumentare l'interfaccia IMyThing
in questo modo:
public interface IMyThing : IEquatable<IMyThing>
{
int Id { get; }
}
L'operatore LINQ avrebbe riconosciuto l'interfaccia IEquatable<T>
e utilizzarlo.
Non voglio fare questo perché:
- Questa è utilizzabile solo con altri oggetti
IMyThing
IEquatable<T>
non era destinato a questo scopo- io non voglio macchiare il mio modello solo per renderlo mockable
Come risolverebbe questo?
Se si sta tentando di testare alcuni scenari complessi durante il metodo 'HasThing()', forse dovrebbe accettare 'IEnumerable'. Perché non "introdurre un ulteriore livello di riferimento indiretto"? –