---
title: D. Test Handlers
---

## Test Handlers?

We want every test run to be entirely independent of other test runs.
If you don't work hard to guarantee that your test runs are fully independent, you can run into hard-to-diagnose
race conditions and inconsistent/flaky tests (the bane of all engineers).

This is where **Test Handlers** come in. We ideally want to define a setup function that we can call once per test case
that creates a fully independent testing environment in the provided scope.

Test Handlers should provide access to:
- A "real" instance of the main object being unit tested
- All of the underlying Fake Clients being used by the main object
- A cleanup function that can be called to clean the environment after a test run finishes

## Examples

```go
type testHandler struct {
    server *server.Server // the "main" client/object being unit tests
    db *fakes.FakeDB // fake client that the main client will use
    cleanup func()
}

func setupTest(t *testing.T) *testHandler {
    fakeDB := &fakes.FakeDB{}
    s := &server.Server{ // this creates a "real" instance of the server client - as far as it knows, at least
        DB: fakeDB,
    }
    return &testHandler{
        cleanup: func() {}, // in this case, we don't do anything with cleanup(), but we have this here for future-proofing.
        server: s,
        db: fakeDB,
    }
}
```
Now every test can start with these same two lines:
```go
func TestServer_CancelEvent(t *testing.T) {
    h := setupTest(t)
    defer h.cleanup()

    ...
}
```
And we will guarantee that every test server has its own unique copy of `fakeDB`, eliminating the risk of contention on a shared resource.