Writing unit test in golang for workflow that waits for signal

Hello. I am trying to write unit test for a workflow which waits on incoming signals. (basically a workflow select).

I am trying to follow the example here:

I get the deadline exceeded error when running or debugging (as soon as I hit select). I even try setTestTimeout to some huge value and it blows up right away.

I see there is an equivalent issue in java here - Issues with Unit Testing a Workflow with signal method

Is there an equivalent work around for go? Thanks

Sorry, which timeout are your referring to?

Are you using registeDelayedCallback to send signals?

I have changed it.

I got this error

workflow execution error (type: workflowName, workflowID: default-test-workflow-id, runID: default-test-run-id): deadline exceeded (type: ScheduleToClose)

Do I need to set some startWorkflowOptions as well?

ScheduleToClose is an activity timeout. So it looks like some activity is timing out in your unit test.

ah i see… I probably need to mock return for all activities first thanks

I will still getting that error, even if I mocked all activities like this

s.env.OnActivity(MigrationCompleteStageActivity, mock.Anything, mock.Anything, mock.Anything).Return(nil)

Question, does the initial parameter ctx for each activity need to be included in the list of mock argument?

Looking at this further, seems my signals never got received by my workflow under test, it just dies panic as soon as I call selector.Select(ctx) inside the workflow

in debug console, I got this

suite.go:63: test panicked: Potential deadlock detected: workflow goroutine “root” didn’t yield for over a second. Maybe as select is blocking?

Are you using any synchronization in the workflow code? Can it block on some non Temporal API? Does it call any external code directly?

Would you ensure that the workflow code obeys all the restrictions?

all the synchronization is done via workflow versions of the go calls. I do launch go routines via workflow.go and also has workflow.waitGroup…

The only other thing would be logging

oh, I do have a for statement wrapping select so it can keep looping

for {
s.Select(ctx)
// do various things
}

Basically keep waiting for new signals until certain conditions are met then exit workflow

The “Potential deadlock detected: workflow goroutine “root” didn’t yield for over a second” error indicates that the workflow is probably spinning on something. It means that the workflow thread didn’t call some Temporal API for at least a second.

I figured out why, I need to RegisterDelayedCallback first before running the workflow. Thanks for your help!

1 Like

Filed an issue to fail on such incorrect usage.