Cómo mockear ILogger con Moq en C#

Resumen

Cuando una función mezcla lógica de negocio con utilidades como un logger, probarla se vuelve incómodo: tu prueba unitaria falla por dependencias que ni siquiera quieres validar. Aquí entra Moq, la librería de C# que te permite simular esas dependencias y enfocar la prueba solo en lo que importa.

Este recorrido toma la función CountOccurrences de un proyecto de string manipulation en Visual Studio y muestra paso a paso cómo aislar la lógica usando un mock de ILogger. Es útil para desarrolladores .NET que escriben pruebas con xUnit y se topan con dependencias inyectadas que estorban.

¿Por qué falla una prueba unitaria cuando hay dependencias externas?

La función CountOccurrences recibe un texto y un carácter, recorre el string con un foreach, cuenta coincidencias y devuelve un entero. Hasta ahí, lógica pura. El problema aparece en una línea adicional: un logger.LogInformation que registra cuántas ocurrencias se encontraron [01:08].

Ese logger es una utilidad genérica, no parte de la lógica de negocio. Pero al ejecutar la prueba sin pasarle una instancia, el objeto llega como null y la prueba revienta.

¿Qué es un mock en pruebas unitarias? Es un objeto ficticio que simula el comportamiento de una dependencia real. No ejecuta la lógica original, solo finge existir para que tu prueba pueda correr sin tocar servicios externos.

¿Cómo detectar el problema con el depurador de Visual Studio?

Cuando la prueba falla sin razón aparente, la herramienta de debug test de Visual Studio te salva. El proceso es directo:

  • Coloca un breakpoint en la línea donde instancias el objeto bajo prueba.
  • Da clic derecho sobre el método de test y elige Debug Test [04:30].
  • Avanza paso a paso con los controles del depurador.
  • Inspecciona variables y observa dónde se rompe el flujo.

Al entrar al método CountOccurrences, el foreach cuenta correctamente, pero la ejecución falla cuando intenta usar logger. La causa: la dependencia llega nula porque nunca se inyectó.

¿Cómo instalar la librería Moq en un proyecto de test?

Moq se instala desde el gestor de paquetes NuGet del proyecto de pruebas, no del proyecto principal. En Visual Studio el flujo es claro:

  1. Abre el Solution Explorer y selecciona el proyecto de test.
  2. Entra a Manage NuGet Packages.
  3. Ve a la pestaña Browse y busca Moq.
  4. Selecciona la primera opción, acepta la licencia y dale Install.

Existen alternativas como AutoFixture o AutoMock, pero Moq es la librería más popular para mocking en C# y la que verás en la mayoría de proyectos .NET. Si trabajas en Visual Studio Code, agregas la referencia manualmente al archivo de proyecto o usas la CLI con dotnet add package Moq.

¿Cómo simular una dependencia con Moq paso a paso?

En la clase StringOperations, el constructor recibe un ILogger<StringOperations> opcional. La prueba inicial no le pasa nada y por eso falla. La solución es crear un mock de esa interfaz y pasar su .Object al constructor [09:15].

El código queda así dentro de la sección de arrange del patrón AAA:

csharp var mockLogger = new Mock<ILogger<StringOperations>>(); var strOperations = new StringOperations(mockLogger.Object); var result = strOperations.CountOccurrences("Hello Platzi", 'l'); Assert.Equal(3, result);

Dos detalles que cambian todo: el mockLogger debe declararse antes de instanciar StringOperations, porque esa clase recibe la dependencia. Y se pasa mockLogger.Object, no el mock directamente, porque ahí vive la instancia simulada que Moq genera internamente.

¿Qué hace exactamente new Mock<T>()? Crea un objeto falso del tipo T que cumple con su contrato pero no ejecuta lógica real. Sirve para que tu clase bajo prueba reciba la dependencia sin ejecutar comportamiento que no te interesa validar.

¿Cómo verificar que la prueba unitaria pase correctamente?

Después de instalar Moq y reescribir el arrange, la prueba se ejecuta y aparece un nuevo error: el Assert.Equal esperaba 2 pero el resultado es 3. La razón es simple y vale la pena revisarla con calma: la palabra Hello Platzi tiene tres letras l, no dos.

Ajustar el valor esperado a 3 hace que la prueba pase. Si en algún momento aparece un error de compilación o referencias nulas relacionadas con Moq, la solución típica es recompilar el proyecto de test para que las referencias se resuelvan correctamente.

¿Cuándo conviene usar mocks en lugar de objetos reales?

Usar mocks tiene sentido en escenarios concretos:

  • Dependencias que escriben en consola, archivos o bases de datos como un logger.
  • Servicios externos vía HTTP que ralentizan la prueba.
  • Interfaces abstractas cuya implementación real no aporta a la lógica que validas.
  • Componentes con efectos colaterales que ensucian el entorno de pruebas.

La idea central es que una prueba unitaria valide una sola unidad de lógica sin arrastrar comportamientos auxiliares. Moq te da exactamente esa frontera limpia.

Con este primer escenario ya tienes la base del mocking en C#. Cuéntame en los comentarios qué dependencias has tenido que simular en tus propios proyectos y qué retos te encontraste al hacerlo.