Утверждение о принятых вызовах ILogger с использованием NSubstitute не совпадает - PullRequest
0 голосов
/ 06 апреля 2020

У меня возникают проблемы при реализации теста для ILogger совпадения вызовов, когда тестируемый метод выдает исключение, и я действительно не могу понять, в чем причина.

Вот так выглядит мой тест Метод:

public async Task My_test_method()
{
    //Arrange

    var _logger = Substitute.For<ILogger<MyType>>();
    var _mockedInnerService = Substitute.For<IMockedInnerService>();
    var _testedService = new TestedService(_mockedInnerService, _logger);

    var errorMessage = "Some problem";
    _mockedInnerService
        .When(async _self => await _self.SomeMethod(Arg.Any<string>(), Arg.Any<string>()))
        .Do(_self => throw new Exception(errorMessage));
    var expectedMessage = $"Error: {errorMessage}";
    var methodParameters = new List<Guid>() { Guid.NewGuid() };

    //Act
    var results = await _testedService.TestedCall(methodParameters);

    //Assert
    await _mockedInnerService
        .Received(1)
        .SomeMethod(Arg.Any<string>(), Arg.Any<string>());
    results
        .Should()
        .BeEmpty();
    _logger
        .Received(1)
        .LogError(Arg.Is<string>(message => message == expectedMessage));
}

И вот как выглядит мой проверенный метод:

public async Task<IList<SomeObject>> TestedCall(IList<Guid> ids)
{

    IList<object> results = null;
    try
    {
        units = await _innerService.SomeMethod("arg", "arg");
    }
    catch (Exception e)
    {
        var msg = "Some problem";
        _logger.LogError(msg);
    }

    return results == null
        ? new List<object>()
        : results.Select(s => new SomeObject(s.Id, s.Code)).ToList();
}

Тест не пройден с таким результатом:

Message: 
    NSubstitute.Exceptions.ReceivedCallsException : Expected to receive exactly 1 call matching:
        Log<Object>(Error, 0, [null], <null>, Func<Object, Exception, String>)
    Actually received no matching calls.
    Received 1 non-matching call (non-matching arguments indicated with '*' characters):
        Log<Object>(Error, 0, *Some problem*, <null>, Func<Object, Exception, String>)

Можете ли вы, ребята, помогите понять что я тут делаю не так?

Спасибо

1 Ответ

2 голосов
/ 06 апреля 2020

Похоже, что метод ILogger<T>.LogError(string) на самом деле является методом расширения. Это означает, что он преобразуется в другой вызов изнутри, то есть Log<Object>(Error, 0, [null], <null>, Func<Object, Exception, String>), который вы видите в выводе. Этот вызов метода может иметь дополнительные аргументы, которые могут не совпадать для каждого вызова метода расширения и, следовательно, могут отличаться между вашим фактическим вызовом и вызовом утверждения.

Чтобы исправить это, вам, вероятно, придется утверждать в базовом методе и используйте Arg.Any<T>(), чтобы игнорировать проблемные аргументы c, которые, вероятно, являются аргументом Func<Object, Exception, String> в конце.

...