diff --git a/server/certificates/mock_test.go b/server/certificates/mock_test.go
index 5d0dde0..644e8a9 100644
--- a/server/certificates/mock_test.go
+++ b/server/certificates/mock_test.go
@@ -4,13 +4,15 @@ import (
 	"testing"
 
 	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/mock"
 
 	"codeberg.org/codeberg/pages/server/database"
 )
 
 func TestMockCert(t *testing.T) {
-	db, err := database.NewTmpDB()
-	assert.NoError(t, err)
+	db := database.NewMockCertDB(t)
+	db.Mock.On("Put", mock.Anything, mock.Anything).Return(nil)
+
 	cert, err := mockCert("example.com", "some error msg", "codeberg.page", db)
 	assert.NoError(t, err)
 	if assert.NotEmpty(t, cert) {
diff --git a/server/database/interface.go b/server/database/interface.go
index 92068c5..7fdbae7 100644
--- a/server/database/interface.go
+++ b/server/database/interface.go
@@ -8,6 +8,9 @@ import (
 	"github.com/rs/zerolog/log"
 )
 
+//go:generate go install github.com/vektra/mockery/v2@latest
+//go:generate mockery --name CertDB --output . --filename mock.go --inpackage --case underscore
+
 type CertDB interface {
 	Close() error
 	Put(name string, cert *certificate.Resource) error
diff --git a/server/database/mock.go b/server/database/mock.go
index 6148287..e7e2c38 100644
--- a/server/database/mock.go
+++ b/server/database/mock.go
@@ -1,49 +1,122 @@
+// Code generated by mockery v2.20.0. DO NOT EDIT.
+
 package database
 
 import (
-	"fmt"
-	"time"
-
-	"github.com/OrlovEvgeny/go-mcache"
-	"github.com/go-acme/lego/v4/certificate"
+	certificate "github.com/go-acme/lego/v4/certificate"
+	mock "github.com/stretchr/testify/mock"
 )
 
-var _ CertDB = tmpDB{}
-
-type tmpDB struct {
-	intern *mcache.CacheDriver
-	ttl    time.Duration
+// MockCertDB is an autogenerated mock type for the CertDB type
+type MockCertDB struct {
+	mock.Mock
 }
 
-func (p tmpDB) Close() error {
-	_ = p.intern.Close()
-	return nil
-}
+// Close provides a mock function with given fields:
+func (_m *MockCertDB) Close() error {
+	ret := _m.Called()
 
-func (p tmpDB) Put(name string, cert *certificate.Resource) error {
-	return p.intern.Set(name, cert, p.ttl)
-}
-
-func (p tmpDB) Get(name string) (*certificate.Resource, error) {
-	cert, has := p.intern.Get(name)
-	if !has {
-		return nil, fmt.Errorf("cert for %q not found", name)
+	var r0 error
+	if rf, ok := ret.Get(0).(func() error); ok {
+		r0 = rf()
+	} else {
+		r0 = ret.Error(0)
 	}
-	return cert.(*certificate.Resource), nil
+
+	return r0
 }
 
-func (p tmpDB) Delete(key string) error {
-	p.intern.Remove(key)
-	return nil
+// Delete provides a mock function with given fields: key
+func (_m *MockCertDB) Delete(key string) error {
+	ret := _m.Called(key)
+
+	var r0 error
+	if rf, ok := ret.Get(0).(func(string) error); ok {
+		r0 = rf(key)
+	} else {
+		r0 = ret.Error(0)
+	}
+
+	return r0
 }
 
-func (p tmpDB) Items(page, pageSize int) ([]*Cert, error) {
-	return nil, fmt.Errorf("items not implemented for tmpDB")
+// Get provides a mock function with given fields: name
+func (_m *MockCertDB) Get(name string) (*certificate.Resource, error) {
+	ret := _m.Called(name)
+
+	var r0 *certificate.Resource
+	var r1 error
+	if rf, ok := ret.Get(0).(func(string) (*certificate.Resource, error)); ok {
+		return rf(name)
+	}
+	if rf, ok := ret.Get(0).(func(string) *certificate.Resource); ok {
+		r0 = rf(name)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).(*certificate.Resource)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(string) error); ok {
+		r1 = rf(name)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
 }
 
-func NewTmpDB() (CertDB, error) {
-	return &tmpDB{
-		intern: mcache.New(),
-		ttl:    time.Minute,
-	}, nil
+// Items provides a mock function with given fields: page, pageSize
+func (_m *MockCertDB) Items(page int, pageSize int) ([]*Cert, error) {
+	ret := _m.Called(page, pageSize)
+
+	var r0 []*Cert
+	var r1 error
+	if rf, ok := ret.Get(0).(func(int, int) ([]*Cert, error)); ok {
+		return rf(page, pageSize)
+	}
+	if rf, ok := ret.Get(0).(func(int, int) []*Cert); ok {
+		r0 = rf(page, pageSize)
+	} else {
+		if ret.Get(0) != nil {
+			r0 = ret.Get(0).([]*Cert)
+		}
+	}
+
+	if rf, ok := ret.Get(1).(func(int, int) error); ok {
+		r1 = rf(page, pageSize)
+	} else {
+		r1 = ret.Error(1)
+	}
+
+	return r0, r1
+}
+
+// Put provides a mock function with given fields: name, cert
+func (_m *MockCertDB) Put(name string, cert *certificate.Resource) error {
+	ret := _m.Called(name, cert)
+
+	var r0 error
+	if rf, ok := ret.Get(0).(func(string, *certificate.Resource) error); ok {
+		r0 = rf(name, cert)
+	} else {
+		r0 = ret.Error(0)
+	}
+
+	return r0
+}
+
+type mockConstructorTestingTNewMockCertDB interface {
+	mock.TestingT
+	Cleanup(func())
+}
+
+// NewMockCertDB creates a new instance of MockCertDB. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
+func NewMockCertDB(t mockConstructorTestingTNewMockCertDB) *MockCertDB {
+	mock := &MockCertDB{}
+	mock.Mock.Test(t)
+
+	t.Cleanup(func() { mock.AssertExpectations(t) })
+
+	return mock
 }