Как правильно проверить, что ILogger.LogCritical был вызван с NSubstitute? - PullRequest
0 голосов
/ 11 декабря 2019

У меня есть трудные времена с NSubstitute, чтобы проверить, был ли вызван метод ILogger.LogCritical(...).

Например, с кодом ниже:

[Fact]
public void TestNSubstituteAgain()
{
    var logger = Substitute.For<ILogger<StockService>>();
    logger.LogCritical(new Exception(), "Hey lads!");
    logger.Received().Log(
        LogLevel.Critical, 
        Arg.Any<EventId>(), 
        Arg.Any<object>(), 
        Arg.Any<Exception>(),
        Arg.Any<Func<object, Exception, string>>()
        );
}

Я получаю это исключение:

Rm.Combo.App.Tests.VirtualParcels.Services.StockServiceTest.TestNSubstituteAgain

NSubstitute.Exceptions.ReceivedCallsException : Expected to receive a call matching:
    Log<Object>(Critical, any EventId, any Object, any Exception, any Func<Object, Exception, String>)
Actually received no matching calls.

   at NSubstitute.Core.ReceivedCallsExceptionThrower.Throw(ICallSpecification callSpecification, IEnumerable`1 matchingCalls, IEnumerable`1 nonMatchingCalls, Quantity requiredQuantity)
   at NSubstitute.Routing.Handlers.CheckReceivedCallsHandler.Handle(ICall call)
   at NSubstitute.Routing.Route.Handle(ICall call)
   at NSubstitute.Core.CallRouter.Route(ICall call)
   at NSubstitute.Proxies.CastleDynamicProxy.CastleForwardingInterceptor.Intercept(IInvocation invocation)
   at Castle.DynamicProxy.AbstractInvocation.Proceed()
   at NSubstitute.Proxies.CastleDynamicProxy.ProxyIdInterceptor.Intercept(IInvocation invocation)
   at Castle.DynamicProxy.AbstractInvocation.Proceed()
   at Castle.Proxies.ObjectProxy_2.Log[TState](LogLevel logLevel, EventId eventId, TState state, Exception exception, Func`3 formatter)
   at Rm.Combo.App.Tests.VirtualParcels.Services.StockServiceTest.TestNSubstituteAgain() in C:\Users\eperret\Desktop\combo\api\Rm.Combo.App.Tests\VirtualParcels\Services\StockServiceTest.cs:line 99
// 1] Ok the call I am making is that ext. method below:
public static void LogCritical(this ILogger logger, Exception exception, string message, params object[] args)
{
    logger.Log(LogLevel.Critical, exception, message, args);
}

// 2] Which forwards to that other ext. method below:
public static void Log(this ILogger logger, LogLevel logLevel, Exception exception, string message, params object[] args)
{
    logger.Log(logLevel, 0, exception, message, args);
}

// 3] and... then here (still an ext. method tho):
public static void Log(this ILogger logger, LogLevel logLevel, EventId eventId, Exception exception, string message, params object[] args)
{
    if (logger == null)
    {
        throw new ArgumentNullException(nameof(logger));
    }

    logger.Log(logLevel, eventId, new FormattedLogValues(message, args), exception, _messageFormatter);
}

// 4] to finally end up with this "direct" interface method:
void Log<TState>(
LogLevel logLevel,
EventId eventId,
TState state,
Exception exception,
Func<TState, Exception, string> formatter);
// Note: which is supposedly what I am gonna ask NSubstitute to check against, right? (since we cannot use NSubstitute `Received` method on ext. method, it has to be the corresponding instance method)

Примечание: FormattedLogValues - это internal struct, поэтому мне действительно пришлось использовать Arg.Any<object>.

Когда я проверяю фактически принятые вызовы, я вижу, чтоУ логгера есть вызов, и я не слишком уверен, насколько он отличается от того, против которого я утверждаю. Как будто я ставлю точку останова на что-то вроде var re = logger.ReceivedCalls(); во время отладки моего модульного теста:

enter image description here

Я действительно не знаю, что не считаетсяправильные параметры утверждения NS Received().

Есть мысли?

1 Ответ

1 голос
/ 11 декабря 2019

Я бы использовал ReceivedWithAnyArgs() (https://nsubstitute.github.io/help/received-calls/), если сопоставление параметров очень сложно. NSubstitute хорошо, если все просто. Если это становится слишком сложным, я, как правило, просто создаю тестовую версию интерфейса(например, ILogger), и зарегистрируйте интересующие меня аргументы из звонков и проверьте их.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...