0

I have written an Azure durable function in F# and am trying to write unit tests, following the guidelines at https://learn.microsoft.com/en-us/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:

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.

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.

Is there any way to mock such a class in an F# test? Rolling my own implementation would be awkward in this case, as DurableOrchestrationContextBase is a large class with many members that would need implementing.

Blisco
  • 601
  • 6
  • 14

1 Answers1

0

In the end I worked around this issue by switching to NSubstitute, which is capable of mocking this kind of class. 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. 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" })
    }

Blisco
  • 601
  • 6
  • 14