diff --git a/internal/config/db.go b/internal/config/db.go
index 56b11d981..4d6a66c6f 100644
--- a/internal/config/db.go
+++ b/internal/config/db.go
@@ -58,12 +58,18 @@ func (c *Config) CloseDb() error {
 // InitDb will initialize the database connection and schema.
 func (c *Config) InitDb() {
 	entity.SetDbProvider(c)
-	entity.Migrate()
+	entity.MigrateDb()
 }
 
-// DropTables drops all tables in the currently configured database (be careful!).
-func (c *Config) DropTables() {
-	entity.DropTables(c.Db())
+// ResetDb drops all tables in the currently configured database and re-creates them.
+func (c *Config) ResetDb(testFixtures bool) {
+	entity.SetDbProvider(c)
+	entity.ResetDb(testFixtures)
+
+	// TODO: Remove when new test fixtures are ready
+	if testFixtures {
+		c.ImportSQL(c.ExamplesPath() + "/fixtures.sql")
+	}
 }
 
 // connectToDatabase establishes a database connection.
diff --git a/internal/config/test.go b/internal/config/test.go
index 6f14a4ac3..e60a0b384 100644
--- a/internal/config/test.go
+++ b/internal/config/test.go
@@ -10,7 +10,6 @@ import (
 
 	_ "github.com/jinzhu/gorm/dialects/mysql"
 	_ "github.com/jinzhu/gorm/dialects/sqlite"
-	"github.com/photoprism/photoprism/internal/entity"
 	"github.com/photoprism/photoprism/internal/thumb"
 	"github.com/photoprism/photoprism/pkg/capture"
 	"github.com/photoprism/photoprism/pkg/fs"
@@ -103,20 +102,7 @@ func NewTestConfig() *Config {
 		log.Fatalf("config: %s", err.Error())
 	}
 
-	c.DropTables()
-
-	// Make sure changes have been written to disk.
-	time.Sleep(250 * time.Millisecond)
-
-	c.InitDb()
-
-	// Make sure changes have been written to disk.
-	time.Sleep(250 * time.Millisecond)
-
-	entity.CreateTestFixtures()
-
-	// TODO: Remove when new test fixtures are ready
-	c.ImportSQL(c.ExamplesPath() + "/fixtures.sql")
+	c.ResetDb(true)
 
 	thumb.JpegQuality = c.ThumbQuality()
 	thumb.PreRenderSize = c.ThumbSize()
diff --git a/internal/entity/entity.go b/internal/entity/entity.go
index 44dbe857c..eb3993dce 100644
--- a/internal/entity/entity.go
+++ b/internal/entity/entity.go
@@ -10,6 +10,8 @@ https://github.com/photoprism/photoprism/wiki/Storage
 package entity
 
 import (
+	"time"
+
 	"github.com/jinzhu/gorm"
 	"github.com/photoprism/photoprism/internal/event"
 )
@@ -22,8 +24,8 @@ func logError(result *gorm.DB) {
 	}
 }
 
-// Migrate creates all tables and inserts default entities as needed.
-func Migrate() {
+// MigrateDb creates all tables and inserts default entities as needed.
+func MigrateDb() {
 	Db().AutoMigrate(
 		&Account{},
 		&File{},
@@ -53,8 +55,8 @@ func Migrate() {
 }
 
 // DropTables drops database tables for all known entities.
-func DropTables(db *gorm.DB) {
-	db.DropTableIfExists(
+func DropTables() {
+	Db().DropTableIfExists(
 		&Account{},
 		&File{},
 		&FileShare{},
@@ -76,3 +78,33 @@ func DropTables(db *gorm.DB) {
 		&Link{},
 	)
 }
+
+// ResetDb drops database tables for all known entities and re-creates them with fixtures.
+func ResetDb(testFixtures bool) {
+	DropTables()
+
+	// Make sure changes have been written to disk.
+	time.Sleep(100 * time.Millisecond)
+
+	MigrateDb()
+
+	if testFixtures {
+		// Make sure changes have been written to disk.
+		time.Sleep(100 * time.Millisecond)
+
+		CreateTestFixtures()
+	}
+}
+
+// InitTestDb connects to and completely initializes the test database incl fixtures.
+func InitTestDb(dsn string) *Gorm {
+	db := &Gorm{
+		Driver: "mysql",
+		Dsn:    dsn,
+	}
+
+	SetDbProvider(db)
+	ResetDb(true)
+
+	return db
+}
diff --git a/internal/entity/entity_test.go b/internal/entity/entity_test.go
index 01bde0f52..7559e8138 100644
--- a/internal/entity/entity_test.go
+++ b/internal/entity/entity_test.go
@@ -15,13 +15,7 @@ func TestMain(m *testing.M) {
 	log.Out = &logBuffer
 	log.SetLevel(logrus.DebugLevel)
 
-	db := &Gorm{
-		Driver: "mysql",
-		Dsn:    "photoprism:photoprism@tcp(photoprism-db:4001)/photoprism?parseTime=true",
-	}
-
-	SetDbProvider(db)
-	Migrate()
+	db := InitTestDb("photoprism:photoprism@tcp(photoprism-db:4001)/photoprism?parseTime=true")
 
 	code := m.Run()