# Unit Testing: Problems Using OnWorkflow

**URL:** <https://community.temporal.io/t/unit-testing-problems-using-onworkflow/6098>\
**Category:** Community Support\
**Tags:** go-sdk, testing\
**Created:** [September 30, 2022, 4:16am UTC](https://community.temporal.io/t/unit-testing-problems-using-onworkflow/6098 "2022-09-30T04:16:21Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![AlbertL](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/albertl/32/2825_2.png) [@AlbertL](https://community.temporal.io/u/AlbertL)\
**Post date:** [September 30, 2022, 4:16am UTC](https://community.temporal.io/t/unit-testing-problems-using-onworkflow/6098/1 "2022-09-30T04:16:22Z")

</div>

Hi,

I think I’m using `OnWorkflow` incorrectly. Could someone enlighten me please? Thanks!

```auto
func SimpleWorkflow(ctx workflow.Context, u []uuid.UUID) error {
	if workflow.GetInfo(ctx).ContinuedExecutionRunID == "" {
		if err := workflow.ExecuteActivity(workflow.WithActivityOptions(ctx, workflow.ActivityOptions{StartToCloseTimeout: 10 * time.Minute}), SimpleActivity).Get(ctx, &u); err != nil {
			return err
		}
	}

	for i, p := range u {
		if i > 10000 {
			return workflow.NewContinueAsNewError(ctx, SimpleWorkflow, u[i:])
		}
		workflow.ExecuteChildWorkflow(ctx, SimpleChildWorkflow, p)
	}
	return nil
}

func SimpleActivity(ctx context.Context) ([]uuid.UUID, error) {
	return nil, nil
}

func SimpleChildWorkflow(ctx workflow.Context, u uuid.UUID) error {
	return nil
}

```

```auto
type SimpleWorkflowUnitTestSuite struct {
	suite.Suite
	testsuite.WorkflowTestSuite
}

func (s *SimpleWorkflowUnitTestSuite) TestSimple() {
	env := s.NewTestWorkflowEnvironment()
	env.RegisterWorkflow(SimpleWorkflow)
	env.RegisterWorkflow(SimpleChildWorkflow)
	env.OnActivity(SimpleActivity, mock.Anything).Return(make([]uuid.UUID, 20000), nil).Once()
	count := 0
	env.OnWorkflow(SimpleChildWorkflow, mock.Anything, mock.Anything).Return(
		func(_ workflow.Context, _ uuid.UUID) error {
			count++
			return nil
		}).Times(10000)
	env.ExecuteWorkflow(SimpleWorkflow, nil)
	s.True(env.IsWorkflowCompleted())
	s.True(workflow.IsContinueAsNewError(env.GetWorkflowError()))
	s.Equal(10000, count) // <<<<<<<<< this fails
	env.AssertExpectations(s.T())
}

func TestSimpleWorkflowUnitTestSuite(t *testing.T) {
	suite.Run(t, new(SimpleWorkflowUnitTestSuite))
}

```

Unexpectedly results in `count` being `0`. How do I set this up such that the mock of `SimpleChildWorkflow` counts the number of times it was called?

Thanks!

Albert

---

<div class="post-metadata">

**Author:** ![krocos](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/krocos/32/328_2.png) [@krocos](https://community.temporal.io/u/krocos)\
**Post date:** [September 30, 2022, 9:08am UTC](https://community.temporal.io/t/unit-testing-problems-using-onworkflow/6098/2 "2022-09-30T09:08:30Z")

</div>

Imo you just do not need to register `SimpleChildWorkflow` in the test. Though I did not try this in action 🙂

---

<div class="post-metadata">

**Author:** ![AlbertL](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/albertl/32/2825_2.png) [@AlbertL](https://community.temporal.io/u/AlbertL)\
**Post date:** [September 30, 2022, 11:35am UTC](https://community.temporal.io/t/unit-testing-problems-using-onworkflow/6098/3 "2022-09-30T11:35:24Z")

</div>

Mmm, when that line is removed, the code panics with:

```auto
unable to find workflow type: SimpleChildWorkflow. Supported types: [SimpleWorkflow]

```

---

<div class="post-metadata">

**Author:** ![krocos](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/krocos/32/328_2.png) [@krocos](https://community.temporal.io/u/krocos)\
**Post date:** [September 30, 2022, 12:11pm UTC](https://community.temporal.io/t/unit-testing-problems-using-onworkflow/6098/4 "2022-09-30T12:11:15Z")

</div>

Use it like this: `env.OnWorkflow("SimpleChildWorkflow", ...`. It is testyfy-like, so…

It seems that all those things you register before are things that will be used in a test as real implementations.

---

<div class="post-metadata">

**Author:** ![AlbertL](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/albertl/32/2825_2.png) [@AlbertL](https://community.temporal.io/u/AlbertL)\
**Post date:** [September 30, 2022, 12:43pm UTC](https://community.temporal.io/t/unit-testing-problems-using-onworkflow/6098/5 "2022-09-30T12:43:44Z")

</div>

The code still panics.

```auto
//env.RegisterWorkflow(SimpleChildWorkflow)
env.OnWorkflow("SimpleChildWorkflow", mock.Anything, mock.Anything).Return(

```

```auto
panic: unable to find workflow type: SimpleChildWorkflow. Supported types: [SimpleWorkflow]

```

---

<div class="post-metadata">

**Author:** ![Chad\_Retz](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/chad_retz/32/1396_2.png) [@Chad\_Retz](https://community.temporal.io/u/Chad_Retz)\
**Post date:** [September 30, 2022, 1:27pm UTC](https://community.temporal.io/t/unit-testing-problems-using-onworkflow/6098/6 "2022-09-30T13:27:38Z")

</div>

You never wait on a child workflow, so the workflow just completes immediately. You should at least confirm the child workflow got started without error much less actually runs without error. Something like this:

```go
func SimpleWorkflow(ctx workflow.Context, u []uuid.UUID) error {
	if workflow.GetInfo(ctx).ContinuedExecutionRunID == "" {
		if err := workflow.ExecuteActivity(workflow.WithActivityOptions(ctx, workflow.ActivityOptions{StartToCloseTimeout: 10 * time.Minute}), SimpleActivity).Get(ctx, &u); err != nil {
			return err
		}
	}

	// Only do the first N, then continue as new with the rest
	const amountToHandle = 5
	toHandle := u
	if len(toHandle) > amountToHandle {
		toHandle = toHandle[:amountToHandle]
	}
	selector := workflow.NewSelector(ctx)
	var err error

	// Start the children
	for _, p := range toHandle {
		selector.AddFuture(workflow.ExecuteChildWorkflow(ctx, SimpleChildWorkflow, p), func(f workflow.Future) {
			err = f.Get(ctx, nil)
		})
	}

	// Wait for all children to complete successfully
	for range toHandle {
		selector.Select(ctx)
		if err != nil {
			return err
		}
	}

	// Return continue as new if there are more
	if len(u) > amountToHandle {
		return workflow.NewContinueAsNewError(ctx, SimpleWorkflow, u[amountToHandle:])
	}
	return nil
}

```

You probably shouldn’t run 10k child workflows like this in a single run due to history size limits and input param limits. You should probably batch it up a bit differently on the caller side.

---

<div class="post-metadata">

**Author:** ![AlbertL](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/albertl/32/2825_2.png) [@AlbertL](https://community.temporal.io/u/AlbertL)\
**Post date:** [September 30, 2022, 3:16pm UTC](https://community.temporal.io/t/unit-testing-problems-using-onworkflow/6098/7 "2022-09-30T15:16:17Z")

</div>

Silly question, is there a way to wait until the child workflow starts? I don’t want to block until all the children workflow have completed.

---

<div class="post-metadata">

**Author:** ![Chad\_Retz](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/chad_retz/32/1396_2.png) [@Chad\_Retz](https://community.temporal.io/u/Chad_Retz)\
**Post date:** [September 30, 2022, 4:09pm UTC](https://community.temporal.io/t/unit-testing-problems-using-onworkflow/6098/8 "2022-09-30T16:09:54Z")

</div>

Absolutely, see [workflow package - go.temporal.io/sdk/workflow - Go Packages](https://pkg.go.dev/go.temporal.io/sdk/workflow#hdr-Child_Workflow). Specifically the future has a getter for a “start” future on it that returns the execution

```go
if err := future.GetChildWorkflowExecution().Get(ctx, nil); err != nil {
	// Problem starting workflow.
	return err
}

```

---

<div class="post-metadata">

**Author:** ![tihomir](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/tihomir/32/6580_2.png) [@tihomir](https://community.temporal.io/u/tihomir)\
**Post date:** [September 30, 2022, 5:11pm UTC](https://community.temporal.io/t/unit-testing-problems-using-onworkflow/6098/9 "2022-09-30T17:11:38Z")

</div>

Just to add, [this](https://community.temporal.io/t/best-way-to-create-an-async-child-workflow/114/2) forum post has good info on starting child async.

---

<div class="post-metadata">

**Author:** ![AlbertL](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/albertl/32/2825_2.png) [@AlbertL](https://community.temporal.io/u/AlbertL)\
**Post date:** [September 30, 2022, 5:36pm UTC](https://community.temporal.io/t/unit-testing-problems-using-onworkflow/6098/10 "2022-09-30T17:36:35Z")

</div>

Perhaps I’m not reading the documentation correctly.

```auto
The Get() method will block until the workflow completes and results are available.

```

from: [workflow package - go.temporal.io/sdk/workflow - Go Packages](https://pkg.go.dev/go.temporal.io/sdk/workflow#hdr-Child_Workflow)

Doesn’t that mean that the parent workflow will wait until the child workflow is completed?

I’ve also verified in code that `Get()` will block until the child workflow is complete.

Update: Ah, nevermind. I missed the `GetChildWorkflowExecution()`.

---

<div class="post-metadata">

**Author:** ![Chad\_Retz](https://sea2.discourse-cdn.com/flex016/user_avatar/community.temporal.io/chad_retz/32/1396_2.png) [@Chad\_Retz](https://community.temporal.io/u/Chad_Retz)\
**Post date:** [September 30, 2022, 5:55pm UTC](https://community.temporal.io/t/unit-testing-problems-using-onworkflow/6098/11 "2022-09-30T17:55:04Z")

</div>

> Doesn’t that mean that the parent workflow will wait until the child workflow is completed?

Not sure I understand the question exactly. Basically if you call “Future.Get()” in a workflow, it waits for “Get()” to complete. If that “Get()” is on a child future, it will wait for the child workflow to complete. If you want to wait for the child workflow to start, use “GetChildWorkflowExecution().Get()” on the child future.
