Docs / ArchitectureKit / Guides / Testing with a Database

Testing with a Database

Some tests need a real database, for example to run commands from end to end. To get one, 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:

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

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

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

func TestMain(m *testing.M) {
  architecturekittest.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:

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

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

  os.Exit(code)
}

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 a few seconds, 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:

database := architecturekittest.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.