DurableFunctions.FSharp icon indicating copy to clipboard operation
DurableFunctions.FSharp copied to clipboard

Move to use DurableOrchestrationContextBase to facilitate unit testing via mocks

Open richardjharding opened this issue 5 years ago • 5 comments

I was attempting to write some unit tests along the lines of this document

I ran into a problem as its not possible to mock the sealed DurableOrchestrationContext and if I create a mock DurableOrchestrationContextBase its not possible to cast to the concrete type in order to pass to the orchestration workflow

Any objection to me creating a pr to make the change?

richardjharding avatar Jul 02 '19 12:07 richardjharding

Nice, that's interesting! I don't have any predisposition against Base classes, so give it a try. I'm curious to see what you can come up with. Thanks a ton!

mikhailshilkov avatar Jul 02 '19 12:07 mikhailshilkov

struggling to see how to do this in a non breaking way - thought I could re-define the builder to use #DurableOrchestrationContextBase which compiles but the orchestration ce still expects a DurableOrchestrationContext so inheritance doesn't work as I had hoped

richardjharding avatar Jul 03 '19 06:07 richardjharding

You should probably replace Context to ContextBase everywhere, and then you should be good, no?

mikhailshilkov avatar Jul 03 '19 06:07 mikhailshilkov

yeah that was my first attempt and that works but that means function definitions such as this break

[<FunctionName("HelloSequence")>]
let Run ([<OrchestrationTrigger>] context: DurableOrchestrationContext) = 
    context |>    
    orchestrator {
      let! hello1 = Activity.callByName<string> "SayHello" "Tokyo"
      let! hello2 = Activity.callByName<string> "SayHello" "Seattle"
      let! hello3 = Activity.callByName<string> "SayHello" "London"

      // returns ["Hello Tokyo!", "Hello Seattle!", "Hello London!"]
      return [hello1; hello2; hello3]
    }

with

error FS0001: Type mismatch. Expecting a    'DurableOrchestra
tionContext -> 'a'    but given a    'DurableOrchestrationContextBase -> System.Threading.Tasks.Task<string list>'
 The type 'DurableOrchestrationContext' does not match the type 'DurableOrchestrationContextBase'

It would have to change to

[<FunctionName("HelloSequence")>]
let Run ([<OrchestrationTrigger>] context: DurableOrchestrationContextBase) = 
    context |>    
    orchestrator {
      let! hello1 = Activity.callByName<string> "SayHello" "Tokyo"
      let! hello2 = Activity.callByName<string> "SayHello" "Seattle"
      let! hello3 = Activity.callByName<string> "SayHello" "London"

      // returns ["Hello Tokyo!", "Hello Seattle!", "Hello London!"]
      return [hello1; hello2; hello3]
    }

so anyone taking the latest version of the library would have to change their code - I was hoping that could be avoided

richardjharding avatar Jul 03 '19 07:07 richardjharding

Ah, thanks for the clarification!

Am I wrong or is it the only example that breaks? If so, I'm fine with this. Honestly, I think this call is awkward anyway, so maybe change it to

    let workflow = orchestrator {
      let! hello1 = Activity.callByName<string> "SayHello" "Tokyo"
      let! hello2 = Activity.callByName<string> "SayHello" "Seattle"
      let! hello3 = Activity.callByName<string> "SayHello" "London"

      // returns ["Hello Tokyo!", "Hello Seattle!", "Hello London!"]
      return [hello1; hello2; hello3]
    }
    Orchestrator.run (workflow, context)

while you are here. This shouldn't require the type change then.

mikhailshilkov avatar Jul 03 '19 08:07 mikhailshilkov