为什么从 F# 调用 Moq 会抛出异常?
Why does this call to Moq from F# throw an exception?
我认为这与在 Verify()
上使用 times
参数有关。
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())
异常消息:
System.ArgumentException : Expression of type 'System.Void' cannot be used for constructor parameter of type 'Microsoft.FSharp.Core.Unit'
Moq 的 Verify
方法有许多重载,如果没有注释,F# 将默认将您指定的表达式解析为期望 Func<IService,'TResult>
的重载,其中 'TResult
是单位,这解释了运行时失败。
你想要做的是显式地使用 Verify
的重载,它需要一个 Action
。
一种选择是使用 Moq.FSharp.Extensions project (available as a package on Nuget),它添加了 2 个扩展方法 VerifyFunc
和 VerifyAction
,从而更容易将 F# 函数解析为基于 Moq 的 C# Action
或 Func
个参数:
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())
另一种选择是使用 Foq, a Moq like mocking library specifically designed for F# users (also available as a Nuget package):
open Foq
[<Test>]
let ``No worries`` () =
let mock = Mock.Of<IService>()
Mock.Verify(<@ mock.DoStuff() @>, never)
我认为这与在 Verify()
上使用 times
参数有关。
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())
异常消息:
System.ArgumentException : Expression of type 'System.Void' cannot be used for constructor parameter of type 'Microsoft.FSharp.Core.Unit'
Moq 的 Verify
方法有许多重载,如果没有注释,F# 将默认将您指定的表达式解析为期望 Func<IService,'TResult>
的重载,其中 'TResult
是单位,这解释了运行时失败。
你想要做的是显式地使用 Verify
的重载,它需要一个 Action
。
一种选择是使用 Moq.FSharp.Extensions project (available as a package on Nuget),它添加了 2 个扩展方法 VerifyFunc
和 VerifyAction
,从而更容易将 F# 函数解析为基于 Moq 的 C# Action
或 Func
个参数:
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())
另一种选择是使用 Foq, a Moq like mocking library specifically designed for F# users (also available as a Nuget package):
open Foq
[<Test>]
let ``No worries`` () =
let mock = Mock.Of<IService>()
Mock.Verify(<@ mock.DoStuff() @>, never)