Je veux vérifier certains journaux enregistrés. J'utilise le noyau intégré d'asp.net, ILogger, et l'injecte avec le DI intégré:
private readonly ILogger<InvoiceApi> _logger;
public InvoiceApi(ILogger<InvoiceApi> logger)
{
_logger = logger;
}
alors je l'utilise comme: _logger.LogError("error));
J'ai essayé de me moquer (avec moq) comme d'habitude par:
MockLogger = new Mock<ILogger<InvoiceApi>>();
et injectez ceci dans le service pour test par:
new InvoiceApi(MockLogger.Object);
puis essayé de vérifier:
MockLogger.Verify(m => m.LogError(It.Is<string>(s => s.Contains("CreateInvoiceFailed"))));
mais ça jette:
Vérification non valide sur un membre non virtuel (avec possibilité de substitution en VB): m => m.LogError
Alors, comment puis-je vérifier ces journaux enregistrés?
Comme @ Nkosi l’ai déjà dit, vous ne pouvez pas vous moquer d’une méthode d’extension. Ce que vous devriez simuler, c'est la méthode ILogger.Log
, à laquelle LogError
appelle . Cela rend le code de vérification un peu maladroit, mais cela devrait fonctionner:
MockLogger.Verify(
m => m.Log(
LogLevel.Error,
It.IsAny<EventId>(),
It.Is<FormattedLogValues>(v => v.ToString().Contains("CreateInvoiceFailed")),
It.IsAny<Exception>(),
It.IsAny<Func<object, Exception, string>>()
)
);
(Vous ne savez pas si cela compile, mais vous obtenez le Gist)
J'ai écrit un court article montrant diverses approches, y compris se moquer de la méthode Log () sous-jacente décrite dans d'autres réponses ici. L'article comprend un rapport complet GitHub avec chacune des différentes options . En fin de compte, ma recommandation est d'utiliser votre propre adaptateur plutôt que de travailler directement avec le type ILogger, si vous devez pouvoir vérifier qu'il est appelé.
LogError
est une méthode d'extension (statique) et non une méthode d'instance. Vous ne pouvez pas "directement" simuler des méthodes statiques (d'où une méthode d'extension) avec un framework moqueur. Par conséquent, Moq ne peut pas simuler et donc vérifier cette méthode. J'ai vu des suggestions en ligne sur l'adaptation/le wrapping de l'interface cible et la simulation de votre comportement, mais cela reviendrait à réécrire si vous avez utilisé la valeur par défaut ILogger
dans votre code à de nombreux endroits. Vous devrez créer 2 nouveaux types, un pour la classe wrapper et l'autre pour l'interface mockable.