diff --git a/internal/internal_workflow_test.go b/internal/internal_workflow_test.go index efa6912d2..448ef20bd 100644 --- a/internal/internal_workflow_test.go +++ b/internal/internal_workflow_test.go @@ -1402,24 +1402,6 @@ func (s *WorkflowUnitTest) Test_MutatingFunctionsInQueries() { s.NoError(env.GetWorkflowError()) } -type updateCallback struct { - accept func() - reject func(error) - complete func(interface{}, error) -} - -func (uc *updateCallback) Accept() { - uc.accept() -} - -func (uc *updateCallback) Reject(err error) { - uc.reject(err) -} - -func (uc *updateCallback) Complete(success interface{}, err error) { - uc.complete(success, err) -} - func (s *WorkflowUnitTest) Test_MutatingFunctionsInUpdateValidator() { env := s.NewTestWorkflowEnvironment() @@ -1438,7 +1420,7 @@ func (s *WorkflowUnitTest) Test_MutatingFunctionsInUpdateValidator() { } env.RegisterWorkflow(wf) env.RegisterDelayedCallback(func() { - env.UpdateWorkflow(updateType, "testID", &updateCallback{}) + env.UpdateWorkflow(updateType, "testID", &TestUpdateCallback{}) }, time.Second) env.ExecuteWorkflow(wf) s.True(env.IsWorkflowCompleted()) diff --git a/internal/workflow_testsuite.go b/internal/workflow_testsuite.go index 4775cf22f..9985fdd58 100644 --- a/internal/workflow_testsuite.go +++ b/internal/workflow_testsuite.go @@ -34,6 +34,7 @@ import ( "github.com/nexus-rpc/sdk-go/nexus" "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" commonpb "go.temporal.io/api/common/v1" enumspb "go.temporal.io/api/enums/v1" @@ -83,6 +84,15 @@ type ( runFn func(args mock.Arguments) waitDuration func() time.Duration } + + // TestUpdateCallback is a basic implementation of the UpdateCallbacks interface for testing purposes. + // Tests are welcome to implement their own version of this interface if they need to test more complex + // update logic. This is a simple implementation to make testing basic Workflow Updates easier. + TestUpdateCallback struct { + OnAccept func() + OnReject func(error) + OnComplete func(interface{}, error) + } ) func newEncodedValues(values *commonpb.Payloads, dc converter.DataConverter) converter.EncodedValues { @@ -767,6 +777,18 @@ func (c *MockCallWrapper) NotBefore(calls ...*MockCallWrapper) *MockCallWrapper return c } +func (uc *TestUpdateCallback) Accept() { + uc.OnAccept() +} + +func (uc *TestUpdateCallback) Reject(err error) { + uc.OnReject(err) +} + +func (uc *TestUpdateCallback) Complete(success interface{}, err error) { + uc.OnComplete(success, err) +} + // ExecuteWorkflow executes a workflow, wait until workflow complete. It will fail the test if workflow is blocked and // cannot complete within TestTimeout (set by SetTestTimeout()). func (e *TestWorkflowEnvironment) ExecuteWorkflow(workflowFn interface{}, args ...interface{}) { @@ -1079,6 +1101,17 @@ func (e *TestWorkflowEnvironment) UpdateWorkflowByID(workflowID, updateName, upd return e.impl.updateWorkflowByID(workflowID, updateName, updateID, uc, args) } +func (e *TestWorkflowEnvironment) UpdateWorkflowNoRejection(updateName string, updateID string, t mock.TestingT, args ...interface{}) { + uc := &TestUpdateCallback{ + OnReject: func(err error) { + require.Fail(t, "update should not be rejected") + }, + OnAccept: func() {}, + OnComplete: func(interface{}, error) {}, + } + e.UpdateWorkflow(updateName, updateID, uc, args) +} + // QueryWorkflowByID queries a child workflow by its ID and returns the result synchronously func (e *TestWorkflowEnvironment) QueryWorkflowByID(workflowID, queryType string, args ...interface{}) (converter.EncodedValue, error) { return e.impl.queryWorkflowByID(workflowID, queryType, args...) diff --git a/internal/workflow_testsuite_test.go b/internal/workflow_testsuite_test.go index 3fc46146b..9abe099c2 100644 --- a/internal/workflow_testsuite_test.go +++ b/internal/workflow_testsuite_test.go @@ -274,12 +274,12 @@ func TestWorkflowIDUpdateWorkflowByID(t *testing.T) { // Test UpdateWorkflowByID works with custom ID env := suite.NewTestWorkflowEnvironment() env.RegisterDelayedCallback(func() { - err := env.UpdateWorkflowByID("my-workflow-id", "update", "id", &updateCallback{ - reject: func(err error) { + err := env.UpdateWorkflowByID("my-workflow-id", "update", "id", &TestUpdateCallback{ + OnReject: func(err error) { require.Fail(t, "update should not be rejected") }, - accept: func() {}, - complete: func(interface{}, error) {}, + OnAccept: func() {}, + OnComplete: func(interface{}, error) {}, }, "input") require.NoError(t, err) }, time.Second) @@ -311,13 +311,13 @@ func TestChildWorkflowUpdate(t *testing.T) { ID: wfID, }) env.RegisterDelayedCallback(func() { - err := env.UpdateWorkflowByID("child-workflow", "child-handler", "1", &updateCallback{ - accept: func() { + err := env.UpdateWorkflowByID("child-workflow", "child-handler", "1", &TestUpdateCallback{ + OnAccept: func() { }, - reject: func(err error) { + OnReject: func(err error) { require.Fail(t, "update failed", err) }, - complete: func(result interface{}, err error) { + OnComplete: func(result interface{}, err error) { if err != nil { require.Fail(t, "update failed", err) } @@ -369,13 +369,7 @@ func TestWorkflowUpdateOrder(t *testing.T) { // Test UpdateWorkflowByID works with custom ID env := suite.NewTestWorkflowEnvironment() env.RegisterDelayedCallback(func() { - env.UpdateWorkflow("update", "id", &updateCallback{ - reject: func(err error) { - require.Fail(t, "update should not be rejected") - }, - accept: func() {}, - complete: func(interface{}, error) {}, - }) + env.UpdateWorkflowNoRejection("update", "id", t) }, 0) env.ExecuteWorkflow(func(ctx Context) (int, error) { @@ -407,14 +401,14 @@ func TestWorkflowNotRegisteredRejected(t *testing.T) { env := suite.NewTestWorkflowEnvironment() var updateRejectionErr error env.RegisterDelayedCallback(func() { - env.UpdateWorkflow("update", "id", &updateCallback{ - reject: func(err error) { + env.UpdateWorkflow("update", "id", &TestUpdateCallback{ + OnReject: func(err error) { updateRejectionErr = err }, - accept: func() { + OnAccept: func() { require.Fail(t, "update should not be accepted") }, - complete: func(interface{}, error) {}, + OnComplete: func(interface{}, error) {}, }) }, 0) @@ -433,36 +427,24 @@ func TestWorkflowUpdateOrderAcceptReject(t *testing.T) { env := suite.NewTestWorkflowEnvironment() // Send 3 updates, with one bad update env.RegisterDelayedCallback(func() { - env.UpdateWorkflow("update", "1", &updateCallback{ - reject: func(err error) { - require.Fail(t, "update should not be rejected") - }, - accept: func() {}, - complete: func(interface{}, error) {}, - }) + env.UpdateWorkflowNoRejection("update", "1", t) }, 0) var updateRejectionErr error env.RegisterDelayedCallback(func() { - env.UpdateWorkflow("bad update", "2", &updateCallback{ - reject: func(err error) { + env.UpdateWorkflow("bad update", "2", &TestUpdateCallback{ + OnReject: func(err error) { updateRejectionErr = err }, - accept: func() { - require.Fail(t, "update should not be rejected") + OnAccept: func() { + require.Fail(t, "update should not be accepted") }, - complete: func(interface{}, error) {}, + OnComplete: func(interface{}, error) {}, }) }, 0) env.RegisterDelayedCallback(func() { - env.UpdateWorkflow("update", "3", &updateCallback{ - reject: func(err error) { - require.Fail(t, "update should not be rejected") - }, - accept: func() {}, - complete: func(interface{}, error) {}, - }) + env.UpdateWorkflowNoRejection("update", "3", t) }, 0) env.ExecuteWorkflow(func(ctx Context) (int, error) { @@ -496,23 +478,11 @@ func TestAllHandlersFinished(t *testing.T) { env := suite.NewTestWorkflowEnvironment() env.RegisterDelayedCallback(func() { - env.UpdateWorkflow("update", "id_1", &updateCallback{ - reject: func(err error) { - require.Fail(t, "update should not be rejected") - }, - accept: func() {}, - complete: func(interface{}, error) {}, - }) + env.UpdateWorkflowNoRejection("update", "id_1", t) }, 0) env.RegisterDelayedCallback(func() { - env.UpdateWorkflow("update", "id_2", &updateCallback{ - reject: func(err error) { - require.Fail(t, "update should not be rejected") - }, - accept: func() {}, - complete: func(interface{}, error) {}, - }) + env.UpdateWorkflowNoRejection("update", "id_2", t) }, time.Minute) env.ExecuteWorkflow(func(ctx Context) (int, error) { @@ -570,33 +540,15 @@ func TestWorkflowAllHandlersFinished(t *testing.T) { env := suite.NewTestWorkflowEnvironment() env.RegisterDelayedCallback(func() { - env.UpdateWorkflow("update", "id_1", &updateCallback{ - reject: func(err error) { - require.Fail(t, "update should not be rejected") - }, - accept: func() {}, - complete: func(interface{}, error) {}, - }) + env.UpdateWorkflowNoRejection("update", "id_1", t) }, 0) env.RegisterDelayedCallback(func() { - env.UpdateWorkflow("update", "id_2", &updateCallback{ - reject: func(err error) { - require.Fail(t, "update should not be rejected") - }, - accept: func() {}, - complete: func(interface{}, error) {}, - }) + env.UpdateWorkflowNoRejection("update", "id_2", t) }, time.Minute) env.RegisterDelayedCallback(func() { - env.UpdateWorkflow("nonWarningHandler", "id_3", &updateCallback{ - reject: func(err error) { - require.Fail(t, "update should not be rejected") - }, - accept: func() {}, - complete: func(interface{}, error) {}, - }) + env.UpdateWorkflowNoRejection("nonWarningHandler", "id_3", t) }, 2*time.Minute) env.RegisterDelayedCallback(func() { @@ -727,13 +679,7 @@ func TestWorkflowUpdateLogger(t *testing.T) { env := suite.NewTestWorkflowEnvironment() env.RegisterDelayedCallback(func() { - env.UpdateWorkflow("logging_update", "id_1", &updateCallback{ - reject: func(err error) { - require.Fail(t, "update should not be rejected") - }, - accept: func() {}, - complete: func(interface{}, error) {}, - }) + env.UpdateWorkflowNoRejection("logging_update", "id_1", t) }, 0) env.RegisterDelayedCallback(func() { diff --git a/testsuite/testsuite.go b/testsuite/testsuite.go index eba27e666..02342e266 100644 --- a/testsuite/testsuite.go +++ b/testsuite/testsuite.go @@ -42,6 +42,9 @@ type ( // MockCallWrapper is a wrapper to mock.Call. It offers the ability to wait on workflow's clock instead of wall clock. MockCallWrapper = internal.MockCallWrapper + + // TestUpdateCallback is a basic implementation of the UpdateCallbacks interface for testing purposes. + TestUpdateCallback = internal.TestUpdateCallback ) // ErrMockStartChildWorkflowFailed is special error used to indicate the mocked child workflow should fail to start.