2

I'm using MOQ to mock a durable entity, but seeing this error:

Extension methods (here: DurableContextExtensions.CallEntityAsync) may not be used in setup / verification expressions.

Here's how I'm doing it:

mockContext.Setup(e => e.CallEntityAsync<List<string>>(It.IsAny<EntityId>(), "EntityFunctionName"))
                .ReturnsAsync(new List<string>() {"one", "two", "three" });

Is there any way I can mock calls to my durable entity?

IronMan
  • 309
  • 4
  • 22

1 Answers1

4

As of Durable Functions 2.3.0, all of our extension methods are now baked directly into the interface, so it should be substantially easier to use Moq with all of these methods and their overloads.

Edit: The previous answer below covers why the previous extension method approach made this dificult.

So this is an inherent limitation of how Moq works with extension methods.

Unfortunately, in the meantime, you will need to find out the core method on IDurableOrchestrationContext that is called by the extension method that provides the overload you are using.

For instance, in this case, DurableContextExtension.CallEntityAsync(EntityId entityId, string operationName) is calling IDurableOrchestrationContext.CallEntityAsync(EntityId entityId, string operationName, object operationInput), with a value of null for operationInput. You can find this by looking at the source code.

This is obviously not an ideal way for mocking, as without looking at our source code, it is difficult to tell if you are attempting to mock an extension method or not at the time of writing your tests. You can use a Moq analyzer to at least catch these errors at compile time, but it still won't tell you which method signature to mock to get rid of the error.

We are proposing getting rid of extension methods altogether for this reason, and just putting all of these signature overloads as interface methods directly, so you can mock any of them safely. This is a breaking change for customers who write their tests by directly implementing the interface, so we are trying to keep this change out of a patch release, and only in a minor release with clear guidance of how to fix those broken by these changes. Look for this to be fixed in version 2.3.0 of the extension.

Connor McMahon
  • 1,318
  • 7
  • 15
  • Hi, I am facing a similar issue with 'CallActivityAsync', which doesn't seem to have an overload. Is there a workaround? – AgentHunt Jun 22 '20 at 07:11
  • @AgentHunt, try [this method](https://learn.microsoft.com/en-us/dotnet/api/microsoft.azure.webjobs.extensions.durabletask.idurableorchestrationcontext.callactivityasync?view=azure-dotnet#Microsoft_Azure_WebJobs_Extensions_DurableTask_IDurableOrchestrationContext_CallActivityAsync__1_System_String_System_Object_). Make sure you are specifying TResult in your Setup method). – Connor McMahon Jun 22 '20 at 16:53
  • I vote for your proposal of lifting the extensionsmethods into the interface, the testing experince of the current solution makes me super tired. – Henrik Gering Aug 18 '20 at 14:21