---
title: Testing Locally
weight: 6
---

There's a few ways to test your subscription code with the event bus libraries.


## Testing Handlers Directly

Event Types, while generated code, are in the end just structs. So the fastest way to get good test coverage is to directly test your handler functions with constructed messages.

Presuming the following handler:

```go
func UpdateHandler(ctx context.Context, h *eventbus.Header, event *user.Update) {
	if event.GetLogin().Updated {
		log.Printf("User %v changed their username from %s to %s",
			event.UserId, User.Login.OldValue, User.Login.Value
		)
	}
}
```

You can then easily test it by constructing various `event` payloads. For example:

```go
msg1 := &user.Update{
	UserId: "123",
	Login: nil // ensure we handle unchanged properly
}

msg2 := user.Update{
	UserId: "345",
	Login: &change.StringChange{
		Updated: true,
		Value: "foobar",
		OldValue: "foo",
	}
}
```

## Testing at the Dispatcher Level

If you want to make sure your mux/dispatcher logic is working for handling multiple different payloads, you can use [DispatchPublisher][] from the `mock` package. This publisher can send multiple messages through your dispatcher, allowing you to verify that routing works as expected.

[DispatchPublisher]: https://godoc.internal.justin.tv/code.justin.tv/eventbus/client/mock#DispatchPublisher

## Testing with Local SQS

If you want a more "functional" or "end-to-end" style test (e.g. using `localstack` to create a local SQS queue), modify the AWS config:

```go
config := aws.NewConfig().
	WithRegion("us-east-1").
	WithEndpoint("http://containername:1234")

client, err := sqsclient.New(sqsclient.Config{
	Dispatcher:     mux.Dispatcher(),
	QueueURL:       "http://containername:1234/my-queue-url",
	OverrideClient: sqs.New(session, config),
})
```

Note that the `Session` parameter is ommitted. Instead, provide an `OverrideClient`.


## Creating Test Payloads {#creating-test-payloads}


For some cases, you may want to create custom payloads for the eventbus client, such as for inserting them into the AWS console or for using with the aws-cli commandline tools. To help with this we provide the [`testhelpers` package](https://godoc.internal.justin.tv/code.justin.tv/eventbus/client/testhelpers) that has tooling for creating payloads at any level of the layer-cake protocol stack.

{{% notice note %}}
<p>By design, these payloads are indistinguishable from real EventBus payloads, down to the byte level, so use caution when sending these payloads into production systems! Alternately, build in some other way to denote test payloads, like using obviously-fake user IDs in your payloads, or timestamps way in the past.</p>
{{% /notice %}}

### Generate SNS payloads

Here we will write a simple single-file Go program to generate a payload that you can paste into your unit tests, calls to Dispatch, or into SNS messages like at the AWS CLI.

Create this main.go which makes a `UserPasswordUpdate` message:

```go
package main

import (
	"fmt"
	"log"
	"time"

	"github.com/gofrs/uuid"

	eventbus "code.justin.tv/eventbus/client"
	"code.justin.tv/eventbus/client/testhelpers"
	"code.justin.tv/eventbus/schema/pkg/user_password"
)

func main() {
	header := &eventbus.Header{
		CreatedAt: time.Date(2020, 2, 27, 14, 15, 0, 0, time.UTC),
		MessageID: uuid.Must(uuid.FromString("2e6ad9e6-b142-441b-9c69-8d7d6e5d5741")),
	}
	message := &user_password.Update{
		UserId: "1234",
	}

	raw, err := testhelpers.MakePayload(header, message)
	if err != nil {
		log.Fatal(err.Error())
	}

	fmt.Printf("Raw message: %#v\n", raw.Bytes())
	fmt.Printf("SNS Message: %s\n", raw.SNSPayload())
}

```
Run this program the usual way you'd expect e.g. `go run main.go` at the command-line.


### Generate SQS payloads

Here's a variant that generates a `UserCreate` and formats it for the SQS cli:

```go
package main

import (
	"fmt"
	"log"

	eventbus "code.justin.tv/eventbus/client"
	"code.justin.tv/eventbus/client/testhelpers"
	"code.justin.tv/eventbus/schema/pkg/user"
)

func main() {
	message := &user.Create{
		UserId:      "123",
		Login:       "FooUser",
		DisplayName: "FooUser",
	}

	raw, err := testhelpers.MakePayload(&eventbus.Header{}, message)
	if err != nil {
		log.Fatal(err.Error())
	}

	snsMessage := raw.FakeSNSMessage()
	body, err := snsMessage.SQSBody()
	if err != nil {
		log.Fatal(err.Error())
	}

	fmt.Printf(`aws sqs send-message --queue-url "https://my-queue" --message-body '%s'`, body)
}
```

{{% notice note %}}
<p>The <code>MakePayload</code> function, for convenience, will take the zero values for time and message ID, replacing them with <code>time.Now().UTC()</code> and <code>uuid.NewV4()</code>. However, this will make the binary output change every invocation. To make predictable binary output for unit tests, manually set your own time and UUID like in our earlier example.</p>
{{% /notice %}}
