php editor Baicao introduces you how to use cadence RegisterDelayedCallback in unit testing to perform the same workflow. In unit testing, we often need to simulate asynchronous operations to ensure the correctness of the code under various circumstances. cadence RegisterDelayedCallback is a powerful tool that can help us simulate delayed callback functions in tests. By using RegisterDelayedCallback, we can easily simulate asynchronous operations, ensure the correctness of the code in various situations, and be able to reproduce and fix potential problems. In this article, we will explore how to use cadence RegisterDelayedCallback to perform the same workflow to help you better unit test.
Is it possible to run unit tests using registerdelayedcallback
that performs the same cadence workflow?
I have the following code that runs the workflow twice, the first execution saves the callback token and the second execution retrieves the saved token to complete the activity asynchronously.
workflow.go
package workflow import ( "context" "encoding/base64" "fmt" "go.uber.org/cadence/activity" "go.uber.org/cadence/workflow" ) type workflowimpl struct { worker.worker client.client } func (w workflowimpl) tactivity(ctx context.context, action string) error { fmt.println("tactivity started", action) if action != "approved" { activityinfo := activity.getinfo(ctx) callbacktoken := base64.stdencoding.encodetostring(activityinfo.tasktoken) fmt.println("save callbacktoken", callbacktoken) // saves callbacktoken. return activity.errresultpending } fmt.println("approved") // do some approved things. // get saved callback token. // call w.completeactivity() with the saved callback token. return nil } func (w workflowimpl) tworkflow(ctx workflow.context, action string) (result string, err error) { fmt.println("tworkflow started", action) waitchannel := workflow.newchannel(ctx) workflow.go(ctx, func(ctx workflow.context) { if err := workflow.executeactivity(ctx, w.tactivity, action).get(ctx, nil); err != nil { // do nothing, keep workflow open. return } waitchannel.send(ctx, "ok") }) var signal string waitchannel.receive(ctx, &signal) return signal, nil }
workflow_test.go
package workflow_test import ( "time" "go.uber.org/cadence/worker" ) func (s *UnitTestSuite) Test_TWorkflow() { env := s.NewTestWorkflowEnvironment() worker := workflow.WorkflowImpl{ Worker: ... Client: ... } s.worker = &worker env.RegisterActivity(s.worker.TActivity) // Delay second TWorkflow. env.RegisterDelayedCallback(func() { env.ExecuteWorkflow(s.worker.TWorkflow, "Approved") }, time.Second*2) env.ExecuteWorkflow(s.worker.TWorkflow, "Noop") s.True(env.IsWorkflowCompleted()) s.NoError(env.GetWorkflowError()) }
The above code is not complete, it does not save the callback token and call completeactivity. For the purpose of testing the sequence, I would just like to see the log of the workflow starting and the activity starting twice, but I don't see that. After the first workflow is started, if there are no active logs, the test will hang until it times out.
What's missing or is it possible to execute the same workflow twice like this?
env.registerdelayedcallback(func() { env.executeworkflow(s.worker.tworkflow, "approved") }, time.second*2)
There is a deadlock here. env
is locked while the callback is running (see source code). And the callback wants to execute the workflow on the same env
, which requires acquiring the same lock on env
(see source code).
Let's try to break the deadlock by running the callback in a new goroutine:
env.registerdelayedcallback(func() { go env.executeworkflow(s.worker.tworkflow, "approved") }, time.second*2)
Now we are panicking:
panic: Current TestWorkflowEnvironment is used to execute s.worker.TWorkflow. Please create a new TestWorkflowEnvironment for s.worker.TWorkflow.
Currently, testworkflowenvironment
cannot run 2 non-parent-child workflows. See Issues with Tracking Tasks to Enable testworkflowenvironment to support testing multiple workflows .
As the panic message suggests, you have to create a new testworkflowenvironment
to execute another workflow (but I'm not sure if it's suitable for your use case).
The above is the detailed content of How can I perform the same workflow using cadence RegisterDelayedCallback in a unit test?. For more information, please follow other related articles on the PHP Chinese website!