简体   繁体   English

在Foq中模拟具有虚拟内部可设置属性的抽象类

[英]Mocking an abstract class with a virtual internally settable property in Foq

I have written an Azure durable function in F# and am trying to write unit tests, following the guidelines at https://docs.microsoft.com/en-us/azure/azure-functions/durable/durable-functions-unit-testing . 我已经在F#中编写了Azure持久函数,并尝试按照https://docs.microsoft.com/zh-cn/azure/azure-functions/durable/durable-functions-unit-testing上的准则编写单元测试。 I have attempted to use Foq to create a mock instance of the abstract class DurableOrchestrationContextBase , but that fails with the following error: 我尝试使用Foq创建抽象类DurableOrchestrationContextBase的模拟实例,但是失败并出现以下错误:

System.TypeLoadException : Method 'set_InstanceId' on type 'Mock.DurableOrchestrationContextBase1953fcc2-be15-41fc-850c-5a5813aace89' from assembly 'Foq.Dynamic, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' is overriding a method that is not visible from that assembly. System.TypeLoadException:类型'Mock.DurableOrchestrationContextBase1953fcc2-be15-41fc-850c-5a5813aace89'中的方法'set_InstanceId'来自程序集'Foq.Dynamic,Version = 0.0.0.0,Culture = neutral,PublicKeyToken = null'覆盖了一种方法在该程序集中不可见。

The error relates to this property: 错误与此属性有关:

public virtual string InstanceId { get; internal set; }

Further investigation shows that Foq is able to mock non-virtual, non-abstract properties with internal setters on abstract C# classes, but can't cope with such properties if they are virtual. 进一步的研究表明,Foq能够使用抽象C#类上的内部setter来模拟非虚拟,非抽象属性,但如果它们是虚拟的,则无法应对。

Is there any way to mock such a class in an F# test? 有什么方法可以在F#测试中模拟此类? Rolling my own implementation would be awkward in this case, as DurableOrchestrationContextBase is a large class with many members that would need implementing. 在这种情况下,滚动我自己的实现会很尴尬,因为DurableOrchestrationContextBase是一个大型类,其中包含许多需要实现的成员。

In the end I worked around this issue by switching to NSubstitute, which is capable of mocking this kind of class. 最后,我通过切换到NSubstitute来解决此问题,该功能可以模拟此类。 NSubstitute's API is relatively easy to use from F#, since (unlike in Moq, for example) you can configure most scenarios without resorting to expression trees, especially if you can leverage structural equality for verifying arguments. NSubstitute的API在F#中相对易于使用,因为(例如,与Moq不同),您可以配置大多数方案而无需求助于表达式树,尤其是当您可以利用结构相等性来验证参数时。 For example: 例如:

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" })
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM