0

我已经在 F# 中编写了一个 Azure 持久函数,并且正在尝试按照https://docs.microsoft.com/en-us/azure/azure-functions/durable/durable-functions-unit-testing上的指南编写单元测试. 我尝试使用 Foq 创建抽象类的模拟实例DurableOrchestrationContextBase,但失败并出现以下错误:

System.TypeLoadException:来自程序集'Foq.Dynamic,Version = 0.0.0.0,Culture = Neutral,PublicKeyToken = null'的类型'Mock.DurableOrchestrationContextBase1953fcc2-be15-41fc-850c-5a5813aace89'上的方法'set_InstanceId'覆盖了一个方法从该组件中看不到。

该错误与此属性有关:

public virtual string InstanceId { get; internal set; }

进一步的调查表明,Foq 能够在抽象 C# 类上使用内部设置器模拟非虚拟、非抽象属性,但如果它们是虚拟的,则无法处理这些属性。

有没有办法在 F# 测试中模拟这样的类?在这种情况下,滚动我自己的实现会很尴尬,因为DurableOrchestrationContextBase有许多需要实现的成员的大类也是如此。

4

1 回答 1

0

最后,我通过切换到 NSubstitute 来解决这个问题,它能够模拟这种类。NSubstitute 的 API 在 F# 中相对易于使用,因为(例如,与 Moq 不同)您可以配置大多数场景而无需借助表达式树,尤其是在您可以利用结构相等性来验证参数的情况下。例如:

let returns<'T> (value: 'T) x = x.Returns(value) |> ignore

[<Fact>]
let ``should call my activity``() =
    task {
        // Arrange
        let context = Substitute.For<DurableOrchestrationContextBase>()
        context.GetInput<SomeType>() |> returns { Foo = 42 }

        // Act
        do! runOrchestrator context

        // Assert
        // In C# you would have to do Arg.Is<SomeClass>(x => x.Bar == 43 && x.Baz == "bla")
        do! context.Received().CallActivityAsync("MyActivity", { Bar = 43; Baz = "bla" })
    }

于 2019-03-18T17:37:05.190 回答