C# 在C ILogger工厂中使用ILogger进行单元测试的静态方法为空

C# 在C ILogger工厂中使用ILogger进行单元测试的静态方法为空,c#,unit-testing,botframework,ilogger,iloggerfactory,C#,Unit Testing,Botframework,Ilogger,Iloggerfactory,各位, 我正在尝试对我的代码进行单元测试,但是我无法让iLogger工厂正常工作 这是我的单元测试代码,可能不正确: LoggerFactory为空 我在互联网上做了很多研究,但是这些都导致了非静态的课堂信息 如果它很重要,它是一个框架项目 任何帮助都将不胜感激 提前感谢。非常感谢@ChetanRanpariya的评论我的问题的答案非常简单: using NUnit.Framework; using Microsoft.Extensions.Logging; using System.Refle

各位,

我正在尝试对我的代码进行单元测试,但是我无法让iLogger工厂正常工作

这是我的单元测试代码,可能不正确:

LoggerFactory为空

我在互联网上做了很多研究,但是这些都导致了非静态的课堂信息

如果它很重要,它是一个框架项目

任何帮助都将不胜感激


提前感谢。

非常感谢@ChetanRanpariya的评论我的问题的答案非常简单:

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);
        }
    }
}

感谢您的帮助。

非常感谢@ChetanRanpariya的评论我的问题的答案非常简单:

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);
        }
    }
}

感谢您的帮助。

下面的示例介绍了如何验证是否使用Moq在ILogger上调用了日志

 _loggerMock.Verify
        (
            l => l.Log
            (
                //Check the severity level
                LogLevel.Error,
                //This may or may not be relevant to your scenario
                It.IsAny<EventId>(),
                //This is the magical Moq code that exposes internal log processing from the extension methods
                It.Is<It.IsAnyType>((state, t) =>
                    //This confirms that the correct log message was sent to the logger. {OriginalFormat} should match the value passed to the logger
                    //Note: messages should be retrieved from a service that will probably store the strings in a resource file
                    CheckValue(state, LogTest.ErrorMessage, "{OriginalFormat}") &&
                    //This confirms that an argument with a key of "recordId" was sent with the correct value
                    //In Application Insights, this will turn up in Custom Dimensions
                    CheckValue(state, recordId, nameof(recordId))
            ),
            //Confirm the exception type
            It.IsAny<NotImplementedException>(),
            //Accept any valid Func here. The Func is specified by the extension methods
            (Func<It.IsAnyType, Exception, string>)It.IsAny<object>()),
            //Make sure the message was logged the correct number of times
            Times.Exactly(1)
        );

    private static bool CheckValue(object state, object expectedValue, string key)
    {
        var keyValuePairList = (IReadOnlyList<KeyValuePair<string, object>>)state;

        var actualValue = keyValuePairList.First(kvp => string.Compare(kvp.Key, key, StringComparison.Ordinal) == 0).Value;

        return expectedValue.Equals(actualValue);
    }

在这个示例中,

有更多关于如何验证是否使用Moq在ILogger上调用了日志的上下文

 _loggerMock.Verify
        (
            l => l.Log
            (
                //Check the severity level
                LogLevel.Error,
                //This may or may not be relevant to your scenario
                It.IsAny<EventId>(),
                //This is the magical Moq code that exposes internal log processing from the extension methods
                It.Is<It.IsAnyType>((state, t) =>
                    //This confirms that the correct log message was sent to the logger. {OriginalFormat} should match the value passed to the logger
                    //Note: messages should be retrieved from a service that will probably store the strings in a resource file
                    CheckValue(state, LogTest.ErrorMessage, "{OriginalFormat}") &&
                    //This confirms that an argument with a key of "recordId" was sent with the correct value
                    //In Application Insights, this will turn up in Custom Dimensions
                    CheckValue(state, recordId, nameof(recordId))
            ),
            //Confirm the exception type
            It.IsAny<NotImplementedException>(),
            //Accept any valid Func here. The Func is specified by the extension methods
            (Func<It.IsAnyType, Exception, string>)It.IsAny<object>()),
            //Make sure the message was logged the correct number of times
            Times.Exactly(1)
        );

    private static bool CheckValue(object state, object expectedValue, string key)
    {
        var keyValuePairList = (IReadOnlyList<KeyValuePair<string, object>>)state;

        var actualValue = keyValuePairList.First(kvp => string.Compare(kvp.Key, key, StringComparison.Ordinal) == 0).Value;

        return expectedValue.Equals(actualValue);
    }

在.

ApplicationLogging.LoggerFactory=mockLoggerFactory.Object中有更多的上下文;这就是你需要做的,一种使你的代码更加可靠的方法是避免静态,并尝试依赖注入——你可以将需要的ILogger传递给任何需要它的类的构造函数。检查像@ZorgarathThanks这样的DI容器,我将检查linkApplicationLogging.LoggerFactory=mockLoggerFactory.Object中的信息;这就是你需要做的,一种使你的代码更加可靠的方法是避免静态,并尝试依赖注入——你可以将需要的ILogger传递给任何需要它的类的构造函数。检查一下像@ZorgarathThanks这样的DI容器,我将检查链接中的信息
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);
        }
    }
}
UtilsVIP.ApplicationLogging.LoggerFactory = mockLoggerFactory.Object;
 _loggerMock.Verify
        (
            l => l.Log
            (
                //Check the severity level
                LogLevel.Error,
                //This may or may not be relevant to your scenario
                It.IsAny<EventId>(),
                //This is the magical Moq code that exposes internal log processing from the extension methods
                It.Is<It.IsAnyType>((state, t) =>
                    //This confirms that the correct log message was sent to the logger. {OriginalFormat} should match the value passed to the logger
                    //Note: messages should be retrieved from a service that will probably store the strings in a resource file
                    CheckValue(state, LogTest.ErrorMessage, "{OriginalFormat}") &&
                    //This confirms that an argument with a key of "recordId" was sent with the correct value
                    //In Application Insights, this will turn up in Custom Dimensions
                    CheckValue(state, recordId, nameof(recordId))
            ),
            //Confirm the exception type
            It.IsAny<NotImplementedException>(),
            //Accept any valid Func here. The Func is specified by the extension methods
            (Func<It.IsAnyType, Exception, string>)It.IsAny<object>()),
            //Make sure the message was logged the correct number of times
            Times.Exactly(1)
        );

    private static bool CheckValue(object state, object expectedValue, string key)
    {
        var keyValuePairList = (IReadOnlyList<KeyValuePair<string, object>>)state;

        var actualValue = keyValuePairList.First(kvp => string.Compare(kvp.Key, key, StringComparison.Ordinal) == 0).Value;

        return expectedValue.Equals(actualValue);
    }