1

我正在使用 F# 和 Foq 为 C# 项目编写单元测试。

我正在尝试设置一个接口的模拟,其方法有一个out参数,我什至不知道如何开始。它可能与代码引用有关,但这就是我的理解结束的地方。

界面是这样的:

public interface IGetTypeNameString
{
    bool For(Type type, out string typeName);
}

在 C# Foq 中,接口的用法如下所示:

[Fact]
public void Foq_Out()
{
    // Arrange
    var name = "result";
    var instance = new Mock<IGetTypeNameString>()
        .Setup(x => x.For(It.IsAny<Type>(), out name))
        .Returns(true)
        .Create();

    // Act
    string resultName;
    var result = instance.For(typeof(string), out resultName);

    // Assert
    Assert.True(result);
    Assert.Equal("result", resultName);
}

至于如何用 F# 实现这一点,我完全迷失了。我尝试了一些类似的东西

let name = "result"
let instance = Mock<IGetTypeNameString>().Setup(<@ x.For(It.IsAny<Type>(), name) @>).Returns(true).Create();

这导致引用表达式带有下划线并带有错误消息

This expression was expected to have type IGetTypeNameString -> Quotations.Expr<'a> but here has type Quotations.Expr<'b>

没有任何迹象表明 a 和 b 应该是什么类型,我不知道如何纠正这个问题。

:?>

(当我使用 时,它变得更加狂野open Foq.Linq;然后错误列表窗口开始告诉我可能的重载与类似的东西Action<'TAbstract> -> ActionBuilder<'TAbstract>,我什至迷路了......)

非常感谢任何帮助或解释!

编辑:

所以,正如这里所说,byref/out 参数不能在代码引用中使用。这可以在 F# 中设置吗?

4

1 回答 1

3

Foq 支持使用 Foq.Linq 命名空间从 C# 设置 C# 输出参数。

IGetTypeNameString接口可以通过对象表达式在 F# 中轻松设置:

let mock = 
    { new IGetTypeNameString with
       member __.For(t,name) = 
          name <- "Name"
          true
    }

对于 F# 中没有类比的声明,如 C# 的受保护成员和 out 参数,您还可以使用SetupByName重载,即:

let mock = 
    Mock<IGetTypeNameString>()
        .SetupByName("For").Returns(true)
        .Create()                
let success, _ = mock.For(typeof<int>)
于 2014-02-03T07:14:32.820 回答