f# - 使用 Foq 模拟 Microsoft.Extensions.Logging.ILogge

我在使用 Foq 模拟 Microsoft ILogger 时遇到困难。

module MockExample

open Microsoft.Extensions.Logging
open NUnit.Framework
open Foq
//open Foq.Linq


// Implementation

type Worker (logger:ILogger) =

    member this.DoSomething (ok:bool) =
        if ok then
            logger.LogInformation("success 1")
        else
            logger.LogError("error 1")


// Test file

[<Test>]
let ``When error should log error`` () =
    
    // 1. let logger = Mock<ILogger>().SetupAction(fun lg -> lg.LogError("error")) ...Create() not availabe

    // 2.
    //let loggerMock = Mock<ILogger>(); 
    //loggerMock.SetupFunc(fun lg -> lg.LogError(It.IsAny<string>())) |> ignore  // .Returns() is not usable
    //let logger = loggerMock.Create()

    let logger = mock()

    // act
    Worker(logger).DoSomething(false)

    verify <@ logger.LogError("error 1") @> once
    //verify <@ logger.LogError("success 1") @> never

测试未通过。
我还尝试了其他语法来尝试“模仿”LogError 签名但没有成功。

[编辑]

正如建议的那样,我正在尝试模拟真正的记录器方法 .Log(logLevel, message, ...),但仍然无法使其正常工作:

基本上我不知道如何模拟这个:

member Log<'TState> : logLevel: LogLevel * eventId: EventId * state: 'TState * ``exception`` : exn * formatter: System.Func<'TState,exn,string> -> unit

提取/注册/比较状态(它包含日志“消息”)。

[编辑2]

作为一种解决方法,我编写了 ILogger 的模拟并且它达到了目的,但我的问题仍然是“如何使用 Foq 做到这一点”?

type LoggerMock () =
    let mutable informations:string list = []
    let mutable errors:string list = []

    member this.LoggedInformations = informations
    member this.LoggedErrors = errors    

    interface ILogger with
        member this.Log(logLevel: LogLevel, eventId: EventId, state: 'TState, ``exception``: exn, formatter: System.Func<'TState,exn,string>): unit = 
            match logLevel with
            | LogLevel.Information -> informations <- informations @ [state.ToString()]
            | LogLevel.Error -> errors <- errors @ [state.ToString()]
            | _ -> ()
        member this.BeginScope(state: 'TState): System.IDisposable = 
            raise (NotImplementedException())
        member this.IsEnabled(logLevel: LogLevel): bool = 
            raise (NotImplementedException())
                

[<Test>]
let ``When error should log error (custom mock)`` () =    
    let logger = LoggerMock()
    Worker(logger).DoSomething(false)
    logger.LoggedErrors |> should contain "error 2"

最佳答案

问题是 .LogError 和 .LogInformation 实际上不是 ILogger 上的方法,而是包装 ILogger 实际定义的日志方法的扩展方法。

你需要模拟的方法是:ILogger.Log Method

我相信扩展方法都会调用那个方法。

关于f# - 使用 Foq 模拟 Microsoft.Extensions.Logging.ILogger,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72445519/

相关文章:

rust - "the size for values of type cannot be know

javascript - Django 和 React : csrf cookie is not b

kubernetes - 由于 'No such file or directory',Kubect

flutter - 如何在 ListView.builder flutter 中正确使用 findC

python - 通过多进程生成的对象标识

java - 这个官方 Xml 模式是否无效或者是 Jaxb 的错误限制

r - qqplot 不会作图。将数据帧转换为向量时出错

node.js - Pug - 包括带有 "include"关键字的 C 代码

python - Gitlab CI 在 Python 脚本输出中换行

reactjs - RTK 查询维持 `isLoading` 缓存失效后自动重新获取