为什么从F#调用Moq抛出异常?

Nic*_*ick 3 f# moq

我认为它与使用times论证有关Verify().

open NUnit.Framework
open Moq

type IService = abstract member DoStuff : unit -> unit

[<Test>]
let ``Why does this throw an exception?``() =
    let mockService = Mock<IService>()
    mockService.Verify(fun s -> s.DoStuff(), Times.Never())
Run Code Online (Sandbox Code Playgroud)

异常消息:

System.ArgumentException:类型'System.Void'的表达式不能用于'Microsoft.FSharp.Core.Unit'类型的构造函数参数

Phi*_*ord 6

Moq的Verify方法有很多重载,如果没有注释,F#默认会将你指定的表达式解析为期望Func<IService,'TResult>where 'TResult为unit 的重载,这解释了运行时的失败.

你想要做的是明确使用过载Verify它接受一个Action.

一种选择是使用Moq.FSharp.Extensions项目(在Nuget上作为一个包提供),其中包括添加2个扩展方法VerifyFunc,VerifyAction并使得更容易将F#函数解析为Moq的基于C#ActionFunc参数:

open NUnit.Framework
open Moq
open Moq.FSharp.Extensions

type IService = abstract member DoStuff : unit -> unit

[<Test>]
let ``Why does this throw an exception?``() =
   let mockService = Mock<IService>()
   mockService.VerifyAction((fun s -> s.DoStuff()), Times.Never())
Run Code Online (Sandbox Code Playgroud)

另一个选择是使用Foq,一个专门为F#用户设计的Moq 模拟库(也可作为Nuget包提供):

open Foq

[<Test>]
let ``No worries`` () =
  let mock = Mock.Of<IService>()
  Mock.Verify(<@ mock.DoStuff() @>, never)
Run Code Online (Sandbox Code Playgroud)