with verifiable unit tests setup objetos mock and c# moq

c# - verifiable - Moq: cómo llegar a un parámetro pasado a un método de un servicio burlado



objetos mock c# (5)

El método de devolución de llamada sin duda funcionará, pero si estás haciendo esto en un método con muchos parámetros, puede ser un poco detallado. Aquí hay algo que he usado para eliminar algunas de las repeticiones.

var mock = new Mock<Handler>(); // do your test new Foo(mock.Object).Bar(22); var arg = new ArgumentCaptor<SomeResponse>(); mock.Verify(h => h.AsyncHandle(arg.Capture())); Assert.NotNull(arg.Value);

Aquí está la fuente de ArgumentCaptor:

public class ArgumentCaptor<T> { public T Capture() { return It.Is<T>(t => SaveValue(t)); } private bool SaveValue(T t) { Value = t; return true; } public T Value { get; private set; } }

Imagina esta clase

public class Foo { private Handler _h; public Foo(Handler h) { _h = h; } public void Bar(int i) { _h.AsyncHandle(CalcOn(i)); } private SomeResponse CalcOn(int i) { ...; } }

Handler de Mo (q) cking en una prueba de Foo, ¿cómo podría verificar lo que Bar() ha pasado a _h.AsyncHandle ?


La respuesta de Gamlor funcionó para mí, pero pensé que ampliaría el comentario de John Carpenter porque estaba buscando una solución que implicara más de un parámetro. Pensé que otras personas que tropezarían con esta página podrían estar en una situación similar. Encontré esta información en la documentación de Moq .

Usaré el ejemplo de Gamlor, pero supongamos que el método AsyncHandle toma dos argumentos: una string y un objeto SomeResponse .

var mock = new Mock<Handler>(); string stringResult = string.Empty; SomeResponse someResponse = null; mock.Setup(h => h.AsyncHandle(It.IsAny<string>(), It.IsAny<SomeResponse>())) .Callback<string, SomeResponse>((s, r) => { stringResult = s; someResponse = r; }); // do your test new Foo(mock.Object).Bar(22); Assert.AreEqual("expected string", stringResult); Assert.IsNotNull(someResponse);

Básicamente, solo necesita agregar otro It.IsAny<>() con el tipo apropiado, agregar otro tipo al método Callback y cambiar la expresión lambda según corresponda.


La respuesta de Gamlor funciona, pero otra forma de hacerlo (y que considero más expresiva en la prueba) es ...

var mock = new Mock<Handler>(); var desiredParam = 47; // this is what you want to be passed to AsyncHandle new Foo(mock.Object).Bar(22); mock.Verify(h => h.AsyncHandle(desiredParam), Times.Once());

Verificar es muy poderoso, y vale la pena tomarse el tiempo para acostumbrarse.


Puede usar It.Is<TValue>() matcher.

var mock = new Mock<Handler>(); new Foo(mock.Object).Bar(22); mock.Verify(h => h.AsyncHandle(It.Is<SomeResponse>(r => r != null )));


Puede usar el método Mock.Callback:

var mock = new Mock<Handler>(); SomeResponse result = null; mock.Setup(h => h.AnsyncHandle(It.IsAny<SomeResponse>())) .Callback<SomeResponse>(r => result = r); // do your test new Foo(mock.Object).Bar(22); Assert.NotNull(result);

Si solo desea verificar algo simple en el argumento pasado, también puede hacerlo directamente:

mock.Setup(h => h.AnsyncHandle(It.Is<SomeResponse>(response => response != null)));