Search code examples
c#unit-testingbotframeworkiloggeriloggerfactory

Unit Testing Static Methods with ILogger in C# ILoggerFactory is Null


everyone,

I'm trying to do unit tests of my code, however I'm not able to get the ILoggerFactory to work

This is my unit test code (it may not be correct):

using NUnit.Framework;
using Microsoft.Extensions.Logging;
using System.Reflection;
using Moq;
using System;
using MyProgramVIP.Bots.Presenter;
using MyProgramVIP.Bots.Model;
using MyProgramVIP.Bots.Utils;

namespace MyProgramVIPTest
{
    public class TestsExample
    {
        [SetUp]
        public void Setup() {
            
        }

        [Test]
        public void TestExample1()
        {
            //Mocks
            var mockLogger = new Mock<ILogger<TicketPresenter>>();
            mockLogger.Setup(
                m => m.Log(
                    LogLevel.Information,
                    It.IsAny<EventId>(),
                    It.IsAny<object>(),
                    It.IsAny<Exception>(),
                    It.IsAny<Func<object, Exception, string>>()));

            var mockLoggerFactory = new Mock<ILoggerFactory>();
            mockLoggerFactory.Setup(x => x.CreateLogger(It.IsAny<string>())).Returns(() => mockLogger.Object);

            //Construción del modelo necesario para la prueba
            ConversationData conversationData = new ConversationData();
            conversationData.ticket = new Ticket();
            conversationData.response = new Response();

            //Invocación del método a probar
            TicketPresenter.getPutTicketMessage(conversationData);

            //Comprobación del funcionamineto
            Assert.AreEqual("ticketType", conversationData.response.cardIdResponse);
        }
    }
}

This is the code of the class I want to test (I've only left the lines of code that fail)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Linq;
using MyProgramVIP.Bots.Interactor.Services;
using MyProgramVIP.Bots.Model;
using MyProgramVIP.Bots.Utils;

namespace MyProgramVIP.Bots.Presenter
{
    public class TicketPresenter
    {
        private static ILogger _logger = UtilsVIP.ApplicationLogging.CreateLogger(MethodBase.GetCurrentMethod().DeclaringType.Name);

        /// <summary>
        /// Función getPutTicketMessage: encargada de comenzar con el flujo de poner un ticket.
        /// </summary>
        /// <param name="conversationData"></param>
        public static void getPutTicketMessage(ConversationData conversationData)
        {
            try
            {
                //Here it crash.
                _logger.LogInformation("INIT getPutTicketMessage");

                //Code..........

                //Never gets here.
                _logger.LogInformation("ENDED getPutTicketMessage");
            }
            catch (Exception ex)
            {
                //Here it crash too.
                _logger.LogError("EXCEPTION getPutTicketMessage" + ex.ToString());
            }
        }
}

This is the code for the help class that's right where the error is:

using System;
using System.Collections.Generic;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Linq;
using MyProgramVIP.Bots.Model;
using MyProgramVIP.Bots.Model.Elements;

namespace MyProgramVIP.Bots.Utils
{
    public class UtilsVIP
    {
        private static ILogger _logger = ApplicationLogging.CreateLogger("ILogger");

        //Other funtions...

        public static class ApplicationLogging
        {
            public static ILoggerFactory LoggerFactory { get; set; }
            public static ILogger CreateLogger<T>() => LoggerFactory.CreateLogger<T>();
            //Here LoggerFactory is null.
            public static ILogger CreateLogger(string categoryName) => LoggerFactory.CreateLogger("VIPLog: " + categoryName);

        }

        //Other funtions...
    }
}

Right on the line where it runs:

LoggerFactory.CreateLogger("VIPLog: " + categoryName);

LoggerFactory is null.

I've done a lot of research on the internet, however it all leads to non-static class information.

In case it's important, it's a Botframework project.

Any help would be appreciated.

Thanks in advance.


Solution

  • Thanks a lot to the comment off @ChetanRanpariya the answer to my question was really simple:

    using NUnit.Framework;
    using Microsoft.Extensions.Logging;
    using System.Reflection;
    using Moq;
    using System;
    using MyProgramVIP.Bots.Presenter;
    using MyProgramVIP.Bots.Model;
    using MyProgramVIP.Bots.Utils;
    
    namespace MyProgramVIPTest
    {
        public class TestsExample
        {
            [SetUp]
            public void Setup() {
                
            }
    
            [Test]
            public void TestExample1()
            {
                //Mocks
                var mockLogger = new Mock<ILogger<TicketPresenter>>();
                mockLogger.Setup(
                    m => m.Log(
                        LogLevel.Information,
                        It.IsAny<EventId>(),
                        It.IsAny<object>(),
                        It.IsAny<Exception>(),
                        It.IsAny<Func<object, Exception, string>>()));
    
                var mockLoggerFactory = new Mock<ILoggerFactory>();
                mockLoggerFactory.Setup(x => x.CreateLogger(It.IsAny<string>())).Returns(() => mockLogger.Object);
    
                //Just add this, I guess is replacing the objet with the mock.
                UtilsVIP.ApplicationLogging.LoggerFactory = mockLoggerFactory.Object;
                
                //Construción del modelo necesario para la prueba
                ConversationData conversationData = new ConversationData();
                conversationData.ticket = new Ticket();
                conversationData.response = new Response();
    
                //Invocación del método a probar
                TicketPresenter.getPutTicketMessage(conversationData);
    
                //Comprobación del funcionamineto
                Assert.AreEqual("ticketType", conversationData.response.cardIdResponse);
            }
        }
    }
    

    Just add this:

    UtilsVIP.ApplicationLogging.LoggerFactory = mockLoggerFactory.Object;
    

    Thanks for the help.