domingo, 8 de junio de 2008

Diferentes tipos de Mock Objects con Rhino Mocks

Rhino Mocks nos permite crear diferentes tipos de Mock Objetcts según nuestras necesidades, en total son 3 Mocks, Dynamic Mocks y Stubs, simplemente vamos a ver un ejemplo autodescriptivo, para ver los tres tipos y sus aplicaciones.

[TestClass]
public class UnitTest1
{
    MockRepository _repository;

    MockRepository Mocker
    {
        get
        {
            if (_repository == null)
                _repository = new MockRepository();
            return _repository;
        }
    }

    /// <summary>
    /// Los mock dynamic no verifican la llamada a ningún tipo de métod
    /// sirven por ejemplo para configurar respuestas a métodos pero no verificar
    /// si son llamados
    /// </summary>
    [TestMethod]
    public void DynamicTest()
    {
        IDummy MockDummy = Mocker.DynamicMock<IDummy>();

        Expect.Call(MockDummy.DummyMethod("")).Return("hola");

        Mocker.ReplayAll();

        //se retorna el valor configurado
        Assert.AreEqual("hola",MockDummy.DummyMethod(""));

        //nada me impide llamar varias veces a un método a pesar de no encontrase
        //configurado para ello, sin embargo no retorna el valor configurado
        Assert.AreEqual(null, MockDummy.DummyMethod(""));

        Mocker.VerifyAll();
    }

    /// <summary>
    /// Un mock (Strict replay)
    /// verifica que se llamen a los métodos esperados y sólo a estos
    /// </summary>
    [TestMethod]
    [ExpectedException(typeof(ExpectationViolationException))]
    public void MockLlamadaMetodoNoEsperado()
    {
        IDummy MockDummy = Mocker.CreateMock<IDummy>();
        
        Mocker.ReplayAll();

        //lanza una excepción de uso inválido porque se llama a un método que no se esperaba
        MockDummy.DummyMethod("");

        Mocker.VerifyAll();
    }
    /// <summary>
    /// Un mock (Strict replay)
    /// verifica que se llamen a los métodos esperados y sólo a estos
    /// </summary>
    [TestMethod]
    [ExpectedException(typeof(ExpectationViolationException))]
    public void MockNoSeLlamoEsperado()
    {
        IDummy MockDummy = Mocker.CreateMock<IDummy>();
        Expect.Call(MockDummy.DummyMethod("")).Return(null);

        Mocker.ReplayAll();

        //lanza una excepción de uso inválido porque no se llamó a un método esperado
        Mocker.VerifyAll();
    }

    /// <summary>
    /// Un stub no tiene comportamiento, es útil para crear objetos
    /// que necesitamos para hacer funcionar otros pero de los que 
    /// no esperamos ningún comportamiento
    /// </summary>
    [TestMethod]
    public void StubTest()
    {
        IUsuario usuario = Mocker.Stub<IUsuario>();

        Mocker.ReplayAll();

        //el stub se comporta como un objeto con propiedades
        usuario.Nombre = "leonardo";

        Assert.AreEqual<string>("leonardo", usuario.Nombre);

        Mocker.VerifyAll();
    }

    /// <summary>
    /// Un stub no tiene comportamiento, es útil para crear objetos
    /// que necesitamos para hacer funcionar otros pero de los que 
    /// no esperamos ningún comportamiento
    /// </summary>
    [TestMethod]
    [ExpectedException(typeof(InvalidOperationException))]
    public void StubNoAceptaComportamientoTest()
    {
        IUsuario usuario = Mocker.Stub<IUsuario>();
        //el stub no acepta comportamiento, lanza una excepción acá
        Expect.Call(usuario.ToString()).Return("usuario");

        Mocker.ReplayAll();

        usuario.Nombre = "leonardo";

        Assert.AreEqual<string>("leonardo", usuario.Nombre);

        Mocker.VerifyAll();
    }
}

Sencillo, hasta la próxima