diff --git a/go-sandbox/activities/benign/activity.go b/go-sandbox/activities/benign/activity.go new file mode 100644 index 0000000..708e258 --- /dev/null +++ b/go-sandbox/activities/benign/activity.go @@ -0,0 +1,24 @@ +package benign + +// @@@SNIPSTART go-benign-activity-error +import ( + "context" + + "go.temporal.io/sdk/temporal" +) + +func MyActivity(ctx context.Context) (string, error) { + result, err := callExternalService() + if err != nil { + // Mark this error as benign since it's expected + return "", temporal.NewApplicationErrorWithOptions( + err.Error(), + "", + temporal.ApplicationErrorOptions{ + Category: temporal.ApplicationErrorCategoryBenign, + }, + ) + } + return result, nil +} +// @@@SNIPEND diff --git a/go-sandbox/activities/benign/activity_test.go b/go-sandbox/activities/benign/activity_test.go new file mode 100644 index 0000000..b9a5d0a --- /dev/null +++ b/go-sandbox/activities/benign/activity_test.go @@ -0,0 +1,45 @@ +package benign_test + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/suite" + "go.temporal.io/sdk/temporal" + "go.temporal.io/sdk/testsuite" + + "my-org/quickstart/activities/benign" +) + +type BenignErrorTestSuite struct { + suite.Suite + testsuite.WorkflowTestSuite +} + +func TestBenignErrorTestSuite(t *testing.T) { + suite.Run(t, new(BenignErrorTestSuite)) +} + +func (s *BenignErrorTestSuite) Test_ErrorIsBenign() { + defer benign.SetCallExternalService(func() (string, error) { return "", benign.ErrNotReady })() + env := s.NewTestActivityEnvironment() + env.RegisterActivity(benign.MyActivity) + + _, err := env.ExecuteActivity(benign.MyActivity) + var appErr *temporal.ApplicationError + s.True(errors.As(err, &appErr)) + s.Equal(temporal.ApplicationErrorCategoryBenign, appErr.Category()) + s.Contains(appErr.Error(), benign.ErrNotReady.Error()) +} + +func (s *BenignErrorTestSuite) Test_Success() { + defer benign.SetCallExternalService(func() (string, error) { return "ready", nil })() + env := s.NewTestActivityEnvironment() + env.RegisterActivity(benign.MyActivity) + + val, err := env.ExecuteActivity(benign.MyActivity) + s.NoError(err) + var result string + s.NoError(val.Get(&result)) + s.Equal("ready", result) +} diff --git a/go-sandbox/activities/benign/export_test.go b/go-sandbox/activities/benign/export_test.go new file mode 100644 index 0000000..5e5c156 --- /dev/null +++ b/go-sandbox/activities/benign/export_test.go @@ -0,0 +1,8 @@ +package benign + +// SetCallExternalService lets tests in package benign_test replace the external call. +func SetCallExternalService(f func() (string, error)) (restore func()) { + original := callExternalService + callExternalService = f + return func() { callExternalService = original } +} diff --git a/go-sandbox/activities/benign/external.go b/go-sandbox/activities/benign/external.go new file mode 100644 index 0000000..ed6dbfd --- /dev/null +++ b/go-sandbox/activities/benign/external.go @@ -0,0 +1,11 @@ +package benign + +import "errors" + +var ErrNotReady = errors.New("external service is not ready yet") + +// callExternalService stands in for a call to a service that is sometimes not +// ready yet. Tests replace it to control the outcome. +var callExternalService = func() (string, error) { + return "", ErrNotReady +}