Injecting dependencies into activities


I have a workflow activity that returns ErrPendingResult, and requires the activity to invoke CompleteActivity.

The code works as expected. However, when writing unit tests, I am unable to inject a mock Temporal Client into the Activity.

Looking at the SDK docs, I saw that passing a client into Context using Workflow Options BackgroundActivityContext was the recommended way of injecting dependencies like this in the past. However, per the SDK docs for backgroundactivitycontext, it is no longer recommended, and says the following:

Instead, we recommend using a struct with fields that contain
dependencies and develop Activity Definitions as struct methods
and then pass all the dependencies on the structure initialization.

Does this mean that all dependencies must be a part of the input struct passed to an activity?

For e.g.

// YourActivityObject is the struct that maintains shared state across Activities.
// If the Worker crashes this Activity object loses its state.
type YourActivityObject struct {
    Message *string
    Number  *int
    TemporalClient client.Client

// YourActivityDefinition is your custom Activity Definition.
// An Activity Definiton is an exportable function.
func (a *YourActivityObject) YourActivityDefinition(ctx context.Context, param YourActivityParam) (*YourActivityResultObject, error) {

This doesn’t work because the Temporal Client is not serializable.

What is the actual recommended approach?


Activity structure doesn’t need to be serializable as it is local to the worker process.

I actually get error like:

unable to decode: json: cannot unmarshal object into Go struct field 
YourActivityObject.TemporalClient of type client.Client

Where do you get this error? Are you instantiating an activity inside the workflow code? Look at the greetings sample that demonstrates how this should be done.

Thank you! That worked. I misunderstood your initial response, and made the Client a part of activity input. This worked like a charm!

1 Like