c# - ¿Cómo puedo usar Rhino Mocks para inspeccionar qué valores se pasaron a un método?
unit-testing mocking (5)
Con la nueva sintaxis Arrange / Act / Assert:
[Test]
public void MyTest()
{
// arrange
IDoStuff doer = MockRepository.GenerateStub<IDoStuff>();
MyClass myClass = new Myclass(doer);
Guid id = Guid.NewGuid();
// act
myClass.Go(new SomeClass(){id = id});
// assert
doer.AssertWasCalled(x => x.DoStuff(
Arg<Someclass>.Matches(y => y.id == id)));
}
Soy nuevo en la burla, y estoy teniendo dificultades para resolver un problema con UnitTesting.
Digamos que tengo este código:
public class myClass{
private IDoStuff _doer;
public myClass(IDoStuff doer){
_doer = doer;
}
public void Go(SomeClass object){
//do some crazy stuff to the object
_doer.DoStuff(object) //this method is void too
}
}
Ok, entonces quiero UNIT probar el método Go. No me importa lo que el objeto _doer le haga al objeto una vez que lo consigue.
SIN EMBARGO, quiero inspeccionar qué ha recibido el objeto _doer.
en el código PSEUDO quiero lograr esto:
[Test]
public void MyTest()
{
IDoStuff doer = Mocker.Mock<IDoStuff>();
Guid id = Guid.NewGuid();
//test Go method
new MyClass(doer).Go(new SomeClass(){id = id});
Assert.AreEqual(id,MockingFramework.Method(DoStuff).GetReceived<SomeClass>().id);
}
¿Es posible usar Rhino y, de ser así, cómo lo logro?
aclamaciones
Creo que lo que tienes es bueno, así sería:
IDoStuff doer = MockRepository.GenerateMock<IDoStuff>();
luego configure la expectativa a través de:
doer.Expect(() => DoStuff(id));
luego al final:
doer.VerifyAllExpectations();
EDITADO a partir de las respuestas de Lee para notar que también puedes hacer cosas como estas:
doer.Expect(d => d.DoStuff(Arg<int>.Is.GreaterThan(5))
o
doer.Expect(d => d.DoStuff(Arg<CustomObject>.Matches(x => x.CustomProperty == "Beef")));
o pruebas similares cuando no desea comparaciones de referencia exactas mediante el uso de los objetos Arg y Arg.
Si solo quiere probar que la instancia de MyClass
pasa su parámetro a doer.Go
entonces puede configurar una expectativa:
SomeClass obj = new SomeClass { id = id };
doer.Expect(d => d.DoStuff(obj));
//test go method
new MyClass(doer).Go(obj);
doer.VerifyAllExpectations();
Sin embargo, si desea verificar que pase algún objeto posiblemente diferente con algún valor particular para una propiedad, entonces puede usar una restricción:
doer.Expect(d => d.DoStuff(null))
.IgnoreArguments()
.Constraints(Property.Value("Id", expectedId));
Todas estas respuestas proporcionan varias formas de hacer lo que desea y todas funcionan. Hay una cosa adicional a tener en cuenta. Si necesita obtener realmente un "nivel bajo" y ver los argumentos pasados a cualquier método GetArgumentsForCallsMadeOn
/ burlado, puede usar GetArgumentsForCallsMadeOn
.
Está un poco desordenado ya que devuelve el objeto [] []. Lo usas así (suponiendo que hayas stubber.InsertData
para aceptar nulo):
var args = stubber.GetArgumentsForCallsMadeOn(s => s.InsertData(null));
args [0] es una matriz de parámetros pasados a InsertData la primera vez que se llamó.
args [1] es una matriz de parámetros pasados a InsertData la segunda vez que se llamó.
etc ...
Por lo tanto, si desea ver el valor entero pasado como el segundo parámetro de la primera invocación de algún método, puede:
var check = (int) args[0][1];
Una vez más, recomendaría uno de los métodos anteriores, pero esto está disponible si necesitas ponerte realmente rudo y sucio para ver los argumentos.
Solo una sugerencia:
Ambas soluciones de Wim Coenen y Patrick Steele son correctas pero, para la primera solución, muy rápido cuando solo hay un parámetro, hay un mensaje de error incorrecto cuando la prueba falla.
Este es un mensaje para mi función con dos parámetros:
IProductChecker.MustPublish (igual a 2, igual a 123X); Número esperado 1, real # 0.
Ahora, ¿cuál de los dos parámetros es incorrecto? ¿Y si los parámetros fueran más?
He preparado una prueba con este código:
//ARRANGE
const string CLASSCODE = "ABC";
const string SUBCLASSCODE = "123X";
var expected = new [] {CLASSCODE, SUBCLASSCODE};
//ACT
SUT.CallMyFunction(chkMock);
var actual = chkMock.GetArgumentsForCallsMadeOn(m => m.MustPublish(null, null))[0];
//Assert
CollectionAssert.AreEqual(expected, actual);
//instead of
//chkMock.AssertWasCalled(m => m.MustPublish(Arg<string>.Is.Equal("2"), Arg<string>.Is.Equal(SUBCLASSCODE)));
Entonces, en este caso, el mensaje es:
CollectionAssert.AreEqual failed. (El elemento en el índice 0 no coincide).
Hola