Actualmente estamos en proceso de pasar de RhinoMocks a NSubstitute.
Tengo un método que toma un objeto de tipo DatabaseParams . Esta clase tiene la siguiente estructura (simplificada):
public class DatabaseParams { public string StoredProcName { get; private set; } public SqlParameter[] Parameters { get; private set; } public DatabaseParams(string storeProcName, SqlParameter[] spParams) { StoredProcName = storeProcName; Parameters = spParams; } }Tengo el siguiente método. Quiero verificar que los argumentos que se le pasan sean correctos:
public interface IHelper { Task<object> ExecuteScalarProcedureAsync(DatabaseParams data); } ¿Cómo pruebo que se pasó una instancia de DatabaseParams a ese método con los valores correctos?
Podría hacer esto en RhinoMocks con algo como esto:
helperMock.Expect(m => m.ExecuteScalarProcedureAsync(Arg<DatabaseHelperParameters>.Matches( p => p.StoredProcName == "up_Do_Something" && p.Parameters[0].ParameterName == "Param1" && p.Parameters[0].Value.ToString() == "Param1Value" && p.Parameters[1].ParameterName == "Param2" && p.Parameters[1].Value.ToString() == "Param2Value" ))).Return(Task.FromResult<DataSet>(null)); El helperMock se burla de la interfaz IHelper que contiene el método ExecuteScalarProcedureAsync .
He descubierto la respuesta yo mismo.
NSubstitute solo necesita usar la llamada .Received() y luego cuando especifica su argumento para el método. Puede especificar la coincidencia de argumentos como un predicado.
Por ejemplo:
helperMock.Received().ExecuteScalarProcedureAsync(Arg.Is<DatabaseParams>( p => p.StoredProcName == "up_Do_Something" && p.Parameters[0].ParameterName == "Param1" && p.Parameters[0].Value.ToString() == "Param1Value" && p.Parameters[1].ParameterName == "Param2" && p.Parameters[1].Value.ToString() == "Param2Value"));Una alternativa es usar Do (consulte https://nsubstitute.github.io/help/actions-with-arguments/ ). Prefiero esto, ya que le permite llamar aserciones contra propiedades específicas de los argumentos, lo que le brinda una mejor retroalimentación sobre qué propiedades específicas del objeto del argumento son incorrectas. Por ejemplo:
StoredProc sp = null; // Guessing the type here helperMock.Received().ExecuteScalarProcedureAsync(Arg.Do<DatabaseParams>(p => sp = p)); // NUnit assertions, but replace with whatever you want. Assert.AreEqual("up_Do_Something", sp.StoredProcName); Assert.AreEqual("Param1", p.Parameters[0].ParameterName); Assert.AreEqual("Param1Value", p.Parameters[0].Value.ToString()); Assert.AreEqual("Param2", p.Parameters[1].ParameterName); Assert.AreEqual("Param2Value", p.Parameters[1].Value.ToString());Un poco tarde para la fiesta, pero me encontré con la misma necesidad. Estoy trabajando con mockito en java, y tienen un asistente de captura de argumentos que me gusta. Es básicamente lo mismo que la respuesta de @Castrohenge
Así que aquí está mi implementación de NSubstitute.
public interface IFoo { void DoSomthing(string stringArg); }Clase de captura de argumentos
public class ArgCapture<T> { private List<T> m_arguments = new List<T>(); public T capture() { T res = Arg.Is<T>(obj => add(obj)); // or use Arg.Compat.Is<T>(obj => add(obj)); for C#6 and lower return res; } public int Count { get { return m_arguments.Count; } } public T this[int index] { get { return m_arguments[index]; } } public List<T> Values { get { return new List<T>(m_arguments);} } private bool add(T obj) { m_arguments.Add(obj); return true; } }Y el caso de prueba de uso
[Test] public void ArgCaptureTest() { IFoo foo1 = Substitute.For<IFoo>(); ArgCapture<string> stringArgCapture = new ArgCapture<string>(); foo1.DoSomthing("firstCall"); foo1.DoSomthing("secondCall"); foo1.Received(2).DoSomthing(stringArgCapture.capture()); Assert.AreEqual(2,stringArgCapture.Count); Assert.AreEqual("firstCall",stringArgCapture[0]); Assert.AreEqual("secondCall", stringArgCapture[1]); }