# Testing with a Database

Some tests need a real database, for example to run commands from end to end.

To get one, use the `dbtest` package:

*(Changed in 2.0)*

```go
import "github.com/thenativeweb/architecturekit-golang/architecturekit/architecturekittest/dbtest"
```

Call the `Store` function with a `*testing.T`, the source, and the schemas to register. It returns a store on a database that all tests of the package share, which the first test that asks for it starts in a container. Options for the store, such as `WithStateCache`, follow the schemas, so that a test runs with the same store as the application:

```go
func TestAcquireBook(t *testing.T) {
  store := dbtest.Store(t, "https://library.eventsourcingdb.io", bookState.Schemas())

  _, err := architecturekit.Execute(context.TODO(), store, acquireBook, AcquireBook{
    BookID: rand.Text(),
    // ...
  })
  if err != nil {
    t.Fatal(err)
  }
}
```

To stop the database once all tests have run, call the `Main` function from `TestMain`:

```go
func TestMain(m *testing.M) {
  dbtest.Main(m)
}
```

If `TestMain` has more to do once the tests have run, such as closing a browser, run the tests yourself, and call the `StopSharedDatabase` function afterwards. It does nothing if no test has started the database. Here, `closeBrowser` stands for whatever else is left to do:

```go
func TestMain(m *testing.M) {
  code := m.Run()
  closeBrowser()

  if err := dbtest.StopSharedDatabase(); err != nil {
    fmt.Fprintln(os.Stderr, err)
    code = 1
  }

  os.Exit(code)
}
```

*Note that the schemas come as a single slice, so that the options can follow. To hand over the schemas of several states, join them with `slices.Concat`, for example `slices.Concat(bookState.Schemas(), readerState.Schemas())`.*

The tests share the events as well, so a test writes to subjects of its own, for example with a random ID in them, and reads only from those. A test that reads more than that, such as a projection from `/`, needs a database of its own. Call the `IsolatedStore` function to start one for the test alone, which is stopped once the test is over. It takes the same arguments as `Store`, and a few seconds to start, so use it only where the shared one would not do.

For a test that connects by itself, such as one that starts a whole server, call the `SharedDatabase` or the `IsolatedDatabase` function. Each returns a `*Database`, whose `URL` and `APIToken` fields are what a client needs. Its `Client` function returns a client, for example to write an event that no command would, and its `Store` function returns a store, as above. Here, `server.Config` stands for the configuration of your application:

```go
database := dbtest.SharedDatabase(t)

config := server.Config{
  DatabaseURL: database.URL.String(),
  APIToken:    database.APIToken,
}
```

*Note that with `-short` every test that asks for a database is skipped, so that the other tests run without Docker.*

*Note that a `nil` option makes `Store`, `IsolatedStore`, and the `Store` function of a `Database` panic before they ask for a database, so with `-short` as well.*

*(Changed in 2.0)* *Note that the database runs the image `thenativeweb/eventsourcingdb:latest`, as the client SDK starts it, rather than a version of your choice. Docker pulls the image only if it is missing, so which release that is depends on what the machine has pulled before. The database runs without a signing key, so its events carry no signature, and a store with `WithSignatureVerification` fails to read them with an error of the category `ErrUnverified`. Signature verification can therefore not be tested with it (see **[Verifying Events](/docs/architecturekit/v1.0/verifying-events)**).*

*Note that `dbtest` is a package of its own because it starts the database with Testcontainers, which brings along the Docker client. A package whose tests only import `architecturekittest`, for example to test deciders and projections, builds without either.*
