为什么Moq验证方法调用抛出异常?

Div*_*ivh 3 f# moq

我无法通过这段代码.

[<Test>]
member public this.Test() =
    let mock = new Mock<IList<string>>()
    let mockObj = mock.Object

    mockObj.Add("aaa")        
    mock.Verify(fun m -> m.Add(It.IsAny<string>()), Times.Once())
Run Code Online (Sandbox Code Playgroud)

我得到的例外情况:

System.ArgumentException : Expression of type 'System.Void' cannot be used for constructor parameter of type 'Microsoft.FSharp.Core.Unit'
Run Code Online (Sandbox Code Playgroud)

我认为它与F#有关,没有正确推断labda表达式的数据类型,但我不知道如何解决这个问题.

Phi*_*ord 5

你是对的,这是调用接受Action或Func的重载方法时F#类型推断的问题.

一种选择是下载Moq.FSharp.Extensions的NuGet和改变你Verify一个明确的VerifyAction,即

open Moq.FSharp.Extensions

type MyTests() = 
    [<Test>]
    member public this.Test() =
        let mock = new Mock<IList<string>>()
        let mockObj = mock.Object       
        mockObj.Add("aaa")        
        mock.VerifyAction((fun m -> m.Add(any())), Times.Once())
Run Code Online (Sandbox Code Playgroud)

在封面下,Moq.FSharp.Extensions只是定义了一个扩展方法VerifyAction,它只需要Action避免歧义:

type Moq.Mock<'TAbstract> when 'TAbstract : not struct with
    member mock.VerifyAction(expression:Expression<Action<'TAbstract>>) =
        mock.Verify(expression)
Run Code Online (Sandbox Code Playgroud)

另一个选择是使用Foq,一个模拟库,它具有与Moq类似的API,但专门设计用于F#,也可以通过Nuget获得:

[<Test>]
member public this.Test() =
    let mock = Mock.Of<IList<string>>()           
    mock.Add("aaa")        
    Mock.Verify(<@ mock.Add(any()) @>, once) 
Run Code Online (Sandbox Code Playgroud)