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

4

我无法让这段代码通过。

[<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())

我收到的异常信息:

System.ArgumentException : Expression of type 'System.Void' cannot be used for constructor parameter of type 'Microsoft.FSharp.Core.Unit'

我相信这与F#未正确推断lambda表达式的数据类型有关,但我不知道如何解决这个问题。

1个回答

6

你说得对,这是使用F#类型推断时调用重载方法(接受Action或Func)时出现的问题。

一个选择是从Nuget下载Moq.FSharp.Extensions,并将你的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())

在底层,Moq.FSharp.Extensions 仅定义了一个扩展方法 VerifyAction,该方法只接受 Action 以避免歧义:
type Moq.Mock<'TAbstract> when 'TAbstract : not struct with
    member mock.VerifyAction(expression:Expression<Action<'TAbstract>>) =
        mock.Verify(expression)

另一个选择是使用 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) 

谢谢您的回答。不过我想知道是否可以明确指定我想要使用的重载? - Divh
1
很抱歉,目前我不知道有一种明确指定该重载的方法,如果您不想引入Moq.FSharp.Extensions,您可以在答案中间引入Moq的类型扩展。 - Phillip Trelford

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接