Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save ssa3512/c825d616e87e2dae59c3242cb1d61280 to your computer and use it in GitHub Desktop.

Select an option

Save ssa3512/c825d616e87e2dae59c3242cb1d61280 to your computer and use it in GitHub Desktop.
ILogger Verification with Moq
using Microsoft.Extensions.Logging;
using Moq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
// More detailed samples here:
// https://github.com/MelbourneDeveloper/RestClient.Net/blob/79cca66e02f83a1043c44f215d374139f40f8c12/src/RestClient.Net.UnitTests/UnitTests.cs#L758
namespace RestClient.Net.UnitTests
{
public static class LogCheckExtensions
{
/// <summary>
/// Verify that the log was called and get access to check the log arguments
/// </summary>
public static void VerifyLog<T, TException>(
this Mock<ILogger<T>> loggerMock,
Expression<Func<object, Type, bool>> match,
LogLevel logLevel,
int times) where TException : Exception
{
loggerMock.Verify
(
l => l.Log
(
//Check the severity level
logLevel,
//This may or may not be relevant to your scenario
//If you need to check this, add a parameter for it
It.IsAny<EventId>(),
//This is the magical Moq code that exposes internal log processing from the extension methods
It.Is<It.IsAnyType>(match),
//Confirm the exception type
It.IsAny<TException>(),
//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(times)
);
}
/// <summary>
/// Verify that the log was called and get access to check the log arguments
/// </summary>
public static void VerifyLog<T>(
this Mock<ILogger<T>> loggerMock,
Expression<Func<object, Type, bool>> match,
LogLevel logLevel,
int times)
=> VerifyLog<T, Exception>(loggerMock, match, logLevel, times);
/// <summary>
/// Check whether or not the log arguments match the expected result
/// </summary>
public static bool CheckValue<T>(this object state, string key, T expectedValue)
=> CheckValue<T>(state, key, (actualValue)
=> (actualValue == null && expectedValue == null) || (actualValue != null && actualValue.Equals(expectedValue)));
/// <summary>
/// Check whether or not the log arguments match the expected result
/// </summary>
public static bool CheckValue<T>(this object state, string key, Func<T, bool> compare)
{
var keyValuePairList = (IReadOnlyList<KeyValuePair<string, object>>)state;
var keyValuePair = keyValuePairList.FirstOrDefault(kvp => string.Compare(kvp.Key, key, StringComparison.Ordinal) == 0);
//Check to make sure we were able to get the key from the dictionary or return false
if (keyValuePair.Key == null) return false;
var actualValue = (T)keyValuePair.Value;
return compare(actualValue);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment