Dobles en Test - Diferencia entre Stub, Fake y Mock

Este va a ser otro post dentro del grupo de post que tengo sobre testing.

 

En post anteriores vimos que es y cómo hacer mock, pero esta no es nuestra única opción cuando queremos simular funcionalidades o respuestas de servicios. 

En este post vamos a ver las diferentes opciones y sus detalles

 

 

1 - Que es dobles en testing? 

La verdad es que no se ni como llamar a lo que voy a explicar en castellano. Pero básicamente hacer un doble es hacer un código que actúa de una forma determinada, la cual es diferente de la original.

 

Hay varias formas de conseguir el resultado que esperamos, y en este post lo vamos a ver. 

dobles en tests

En nuestro caso tenemos un código que inserta en una base de datos y este código esta tras una interfaz llamada IArticulosRepository.

public interface IArticulosRepository
{
    int InsertarArticulo(string contenido, string titulo, int autorId);
    Articulo GetArticulo(int id);
}

 

 

2 - Que es mock?

El vídeo que vimos sobre mock tenía bastante en detalle, y no quiero entrar en la repetición. 

 

Pero para resumirlo, es añadir configuración en el test, para que ciertos métodos actúen de una forma u otra, esta configuración se hace a nivel de cada test de forma individual. Obviamente se pueden programar para que varios test tengan dicha configuración, pero lo normal es que sean individuales. En C# normalmente utilizaremos la librería Moq.

 

Aqui podemos ver un ejemplo, con la interfaz anterior.

Mock<IArticulosRepository> articuloRepo = new Mock<IArticulosRepository>();
Mock<IAutorRepository> autorRepo = new Mock<IAutorRepository>();
autorRepo.Setup(a => a.AutorValido(It.IsAny<int>())).Returns(true);

articuloRepo.Setup(a => a.InsertarArticulo(contenido, titulo, autorId)).Returns(1);
articuloRepo.Setup(a => a.GetArticulo(1)).Returns(new Articulo()
{
    Autor = new Autor()
    {
        AutorId = autorId,
        Nombre = "test"
    },
    Contenido = contenido,
    Fecha = DateTime.UtcNow,
    Id = 1,
    Titulo = titulo
});

Tenemos que definir la respuesta de cada método, incluyendo los parámetros. por ejemplo, si sabemos que el código va a consultar los ID 1 y 2 tenemos que hacer mock de GetArticulos 1 y 2

Nota: se puede configurar para que devuelva GetArticulos(It.IsAny<Int>).return(..) y nos devolverá el mismo resultado para ambos, pero no suele ser lo normal. 

 

Si quieres más detalles sobre mock, te recomiendo que le des un vistazo a mi post sobre mock en test unitarios.

 

 

3 - Qué es Stub en tests?

La segunda de las formas en las que podemos hacer un doble es creando un stub.

Crear un stub significa crear una clase que siempre va a devolver lo mismo.

 

Por ejemplo en nuestro caso, implementamos la interfaz en una clase y devolvemos siempre la misma información a diferencia del id, que es el que pasamos como parámetro al método:

public class ArticulosStub : IArticulosRepository
{
    public int InsertarArticulo(string contenido, string titulo, int autorId)
    {
        return 1;
    }

    public Articulo GetArticulo(int id)
    {
        return new Articulo()
        {
            Autor = new Autor()
            {
                AutorId = 1,
                Nombre = "test"
            },
            Contenido = "contenido",
            Fecha = DateTime.UtcNow,
            Id = id,
            Titulo = "titulo"
        };
    }
}

Esto quiere decir, que da igual si un id en particular existe o no, la información de GetArticulos siempre será “correcta”.

 

 

4 - Que es Fake en test?

Finalmente vamos a ver que es un fake, un fake no es más que una implementación de la interfaz en su totalidad, pero obviamente que solo funciona dentro de los tests, por ejemplo, en nuestro caso cuando hacemos InsertarArticulo podemos hacerlo en una lista, así, cuando hagamos GetArticulo lo leeremos de la lista.

public class FakeArticulos : IArticulosRepository
{
    public List<Articulo> Articulos { get; set; }

    public int currentIdentifier { get; private set; }
    
    public FakeArticulos()
    {
        Articulos = new List<Articulo>();
        currentIdentifier = 0;
    }


    public int InsertarArticulo(string contenido, string titulo, int autorId)
    {
        Articulo articulo = new Articulo()
        {
            Autor = new Autor()
            {
                AutorId = autorId,
                Nombre = "test"
            },
            Contenido = contenido,
            Fecha = DateTime.UtcNow,
            Id = ++currentIdentifier,
            Titulo = titulo
        };

        Articulos.Add(articulo);
        
        return articulo.Id;
    }

    public Articulo GetArticulo(int id)
        => Articulos.FirstOrDefault(articulo => articulo.Id == id);

}

 

Crear fakes no es tarea sencilla, depende de cómo sea la clase que quieres implementar puede ser bastante compleja, en comparación con hacer mock por ejemplo.

 

 

5 - Mock vs Stub vs Fake, ¿Cuál elegir?

Va a depender de las situaciones, pero personalmente recomiendo utilizar mock siempre que se pueda, por ejemplo para testear una funcionalidad o un caso de uso, es más fácil reutilizar los mocks cuando sea necesario que implementar todo con fake, ya que por norma general requiere menos mantenimiento. 

 

Stub la verdad es que no los utilizo en el mundo real, por lo mismo de antes, es más fácil de ver y entender la funcionalidad de un test con stub

 

En el mundo real los fakes se suelen hacer cuando tenemos tests que afectan a otros o como parte de un sistema que nos permita o facilite crear tests de integración, por ejemplo tenemos un sistema de microservicios y para la comunicación asíncrona en vez de realizar llamadas con productor consumidor las simulamos en memoria, y simulamos dichos eventos generados también. 

 

Así que debemos utilizar lo que nos venga mejor para cada situación, pero cuidado con los Fakes y con duplicar funcionalidades, uno puede acabar en un agujero muy profundo.

 


Uso del bloqueador de anuncios adblock

Hola!

Primero de todo bienvenido a la web de NetMentor donde podrás aprender programación en C# y .NET desde un nivel de principiante hasta más avanzado.


Yo entiendo que utilices un bloqueador de anuncios como AdBlock, Ublock o el propio navegador Brave. Pero te tengo que pedir por favor que desactives el bloqueador para esta web.


Intento personalmente no poner mucha publicidad, la justa para pagar el servidor y por supuesto que no sea intrusiva; Si pese a ello piensas que es intrusiva siempre me puedes escribir por privado o por Twitter a @NetMentorTW.


Si ya lo has desactivado, por favor recarga la página.


Un saludo y muchas gracias por tu colaboración

© copyright 2024 NetMentor | Todos los derechos reservados | RSS Feed

Buy me a coffee Invitame a un café