locked
Moq and Microsoft.Extensions.Logging.ILogger unit tests failing after Microsoft.Extensions.Logging.Abstractions update RRS feed

  • Question

  • Hello,

    Some of my unit tests are failing after updating Microsoft.Extensions.Logging.Abstractions from Version=2.0.0.0 to Version=3.1.1.0.

    I have an ILogger mocked as so:

                var loggerMock = new Mock<ILogger<BillingEventProcessor>>();            
                loggerMock.Setup(l => l.Log(
                    It.IsAny<LogLevel>(), 
                    It.IsAny<EventId>(), 
                    It.IsAny<IReadOnlyList<KeyValuePair<string, object>>>(), 
                    It.IsAny<Exception>(), 
                    It.IsAny<Func<object, Exception, string>>()));

    And a unit that verifies a call to Log() has been made:

    logger.Verify(l => l.Log(
                    It.IsAny<LogLevel>(), 
                    It.IsAny<EventId>(),
                    It.IsAny<IReadOnlyList<KeyValuePair<string, object>>>(),
                    It.IsAny<Exception>(), 
                    It.IsAny<Func<object, Exception, string>>())
                );

    Prior to updating, the IReadOnlyList<KeyValuePair<string, object>> type was of type FormattedLogValues.

    In v2, FormattedLogValues was a public class but in v3.1.1, FormattedLogValues is an internal readonly struct. This changes appears to be the source of the test failure.

    I've tried using It.IsAny<object> for that 3rd parameter instead of the IReadOnlyList or FormattedLogValues, but I didn't have any luck with that.

    Anyone know how I can alter this test code to make the test pass? I can see from debugging info that a call to the Log method is made as expected, I just can't figure out how to set up these mocks correctly with the internal readonly struct parameter.

    This is a .NET Core 2.2 project.

    Monday, May 11, 2020 8:40 PM

All replies

  • How are you using the logger in the program for what purpose? 

    Monday, May 11, 2020 9:59 PM
  • Hi Dudeman 3000,

    Thank you for posting here.

    This package has a repository on GitHub, there are dedicated staff to maintain it, maybe you can ask this question here.

    dotnet / extensions

    The Visual C# forum discusses and asks questions about the C# programming language, IDE, libraries, samples, and tools.

    Best Regards,

    Timon


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Tuesday, May 12, 2020 3:23 AM
  • Are you sure about the signature. Here's what I see for the ILogger<T> interface's Log method.

    public void Log<TState> (Microsoft.Extensions.Logging.LogLevel logLevel, Microsoft.Extensions.Logging.EventId eventId, TState state, Exception exception, Func<TState,Exception,string> formatter);

    Therefore the third parameter in your example is going to be of type TState which is what the Log method overload takes. TState is the parameter you pass to the method. You didn't post the code that is actually under test so are you calling something that ultimately calls Log and you want to verify it or are you calling Log directly. If the former then why? Logging shouldn't be something you need to be testing. If the latter then your unit test would need to change to call Log with whatever state you want. Therefore whether it is the formally public FormattedLogValues or not isn't relevant.

    As for Moq if you don't care about the value being passed then just use It.IsAny(). Note that Moq has a special syntax for method that are themselves generic allowing you to accept any of any (if that makes sense). Refer to their quickstart guide.


    Michael Taylor http://www.michaeltaylorp3.net

    Tuesday, May 12, 2020 1:28 PM