diff --git a/modules/test/apis/common.go b/modules/test/apis/common.go
index 494ed537..5c88455f 100644
--- a/modules/test/apis/common.go
+++ b/modules/test/apis/common.go
@@ -33,37 +33,42 @@ type Handler struct {
 // APIFixture is a base struct to implement OpenStack API simulators for the
 // EnvTest.
 type APIFixture struct {
-	log        logr.Logger
-	server     *FakeAPIServer
-	ownsServer bool
-	urlBase    string
+	Log        logr.Logger
+	Server     *FakeAPIServer
+	OwnsServer bool
+	URLBase    string
 }
 
-func (f *APIFixture) logRequest(r *http.Request) {
-	f.log.Info("OpenStack API request", "method", r.Method, "URI", r.RequestURI)
+// LogRequest logs details of the http.Request
+func (f *APIFixture) LogRequest(r *http.Request) {
+	f.Log.Info("OpenStack API request", "method", r.Method, "URI", r.RequestURI)
 }
 
 // Cleanup stops the embedded http server if it was created by the fixture
 // during setup
 func (f *APIFixture) Cleanup() {
-	if f.ownsServer {
-		f.server.Cleanup()
+	if f.OwnsServer {
+		f.Server.Cleanup()
 	}
 }
 
 // Endpoint is the URL the fixture's embedded http server listening on
 func (f *APIFixture) Endpoint() string {
-	return f.server.Endpoint() + f.urlBase
+	return f.Server.Endpoint() + f.URLBase
 }
 
-func (f *APIFixture) unexpectedRequest(w http.ResponseWriter, r *http.Request) {
-	f.log.Info("Unexpected OpenStackAPI request", "method", r.Method, "URI", r.RequestURI)
+// UnexpectedRequest sends a HTTP 500 response. Use it if the request is
+// understood but not implemented by the fixture
+func (f *APIFixture) UnexpectedRequest(w http.ResponseWriter, r *http.Request) {
+	f.Log.Info("Unexpected OpenStackAPI request", "method", r.Method, "URI", r.RequestURI)
 	w.WriteHeader(500)
 	fmt.Fprintf(w, "Unexpected OpenStackAPI request %s %s", r.Method, r.RequestURI)
 }
 
-func (f *APIFixture) internalError(err error, msg string, w http.ResponseWriter, r *http.Request) {
-	f.log.Info("Internal error", "method", r.Method, "URI", r.RequestURI, "error", err, "message", msg)
+// InternalError sends a HTTP 500 response Use it if there was an unexpected
+// error during the request processing
+func (f *APIFixture) InternalError(err error, msg string, w http.ResponseWriter, r *http.Request) {
+	f.Log.Info("Internal error", "method", r.Method, "URI", r.RequestURI, "error", err, "message", msg)
 	w.WriteHeader(500)
 	fmt.Fprintf(w, "Internal error in %s %s: %s: %v", r.Method, r.RequestURI, msg, err)
 }
diff --git a/modules/test/apis/keystone.go b/modules/test/apis/keystone.go
index 94af1f1d..e21e3d45 100644
--- a/modules/test/apis/keystone.go
+++ b/modules/test/apis/keystone.go
@@ -68,7 +68,7 @@ func NewKeystoneAPIFixtureWithServer(log logr.Logger) *KeystoneAPIFixture {
 	server := &FakeAPIServer{}
 	server.Setup(log)
 	fixture := AddKeystoneAPIFixture(log, server)
-	fixture.ownsServer = true
+	fixture.OwnsServer = true
 	return fixture
 }
 
@@ -78,10 +78,10 @@ func NewKeystoneAPIFixtureWithServer(log logr.Logger) *KeystoneAPIFixture {
 func AddKeystoneAPIFixture(log logr.Logger, server *FakeAPIServer) *KeystoneAPIFixture {
 	fixture := &KeystoneAPIFixture{
 		APIFixture: APIFixture{
-			server:     server,
-			log:        log,
-			urlBase:    "/identity",
-			ownsServer: false,
+			Server:     server,
+			Log:        log,
+			URLBase:    "/identity",
+			OwnsServer: false,
 		},
 		Users:   map[string]users.User{},
 		Domains: map[string]domains.Domain{},
@@ -111,16 +111,16 @@ func (f *KeystoneAPIFixture) registerNormalHandlers() {
 }
 
 func (f *KeystoneAPIFixture) registerHandler(handler Handler) {
-	f.server.mux.HandleFunc(f.urlBase+handler.Pattern, handler.Func)
+	f.Server.AddHandler(f.URLBase+handler.Pattern, handler.Func)
 }
 
 // HandleVersion responds with a valid keystone version response
 func (f *KeystoneAPIFixture) HandleVersion(w http.ResponseWriter, r *http.Request) {
-	f.logRequest(r)
+	f.LogRequest(r)
 	// The /identity URL matches to every request if no handle registered with a more
 	// specific URL pattern
-	if r.RequestURI != f.urlBase+"/" {
-		f.unexpectedRequest(w, r)
+	if r.RequestURI != f.URLBase+"/" {
+		f.UnexpectedRequest(w, r)
 		return
 	}
 
@@ -149,14 +149,14 @@ func (f *KeystoneAPIFixture) HandleVersion(w http.ResponseWriter, r *http.Reques
 			 }
 			 `, f.Endpoint())
 	default:
-		f.unexpectedRequest(w, r)
+		f.UnexpectedRequest(w, r)
 		return
 	}
 }
 
 // HandleToken responds with a valid keystone token
 func (f *KeystoneAPIFixture) HandleToken(w http.ResponseWriter, r *http.Request) {
-	f.logRequest(r)
+	f.LogRequest(r)
 	switch r.Method {
 	case "POST":
 		w.Header().Add("Content-Type", "application/json")
@@ -185,21 +185,21 @@ func (f *KeystoneAPIFixture) HandleToken(w http.ResponseWriter, r *http.Request)
 			 }
 			`, f.Endpoint())
 	default:
-		f.unexpectedRequest(w, r)
+		f.UnexpectedRequest(w, r)
 		return
 	}
 }
 
 // HandleUsers handles the happy path of GET /v3/users and POST /v3/users API
 func (f *KeystoneAPIFixture) HandleUsers(w http.ResponseWriter, r *http.Request) {
-	f.logRequest(r)
+	f.LogRequest(r)
 	switch r.Method {
 	case "GET":
 		f.GetUsers(w, r)
 	case "POST":
 		f.CreateUser(w, r)
 	default:
-		f.unexpectedRequest(w, r)
+		f.UnexpectedRequest(w, r)
 		return
 	}
 }
@@ -225,7 +225,7 @@ func (f *KeystoneAPIFixture) GetUsers(w http.ResponseWriter, r *http.Request) {
 
 	bytes, err := json.Marshal(&s)
 	if err != nil {
-		f.internalError(err, "Error during marshalling response", w, r)
+		f.InternalError(err, "Error during marshalling response", w, r)
 		return
 	}
 	w.Header().Add("Content-Type", "application/json")
@@ -237,7 +237,7 @@ func (f *KeystoneAPIFixture) GetUsers(w http.ResponseWriter, r *http.Request) {
 func (f *KeystoneAPIFixture) CreateUser(w http.ResponseWriter, r *http.Request) {
 	bytes, err := io.ReadAll(r.Body)
 	if err != nil {
-		f.internalError(err, "Error reading request body", w, r)
+		f.InternalError(err, "Error reading request body", w, r)
 		return
 	}
 	var s struct {
@@ -245,7 +245,7 @@ func (f *KeystoneAPIFixture) CreateUser(w http.ResponseWriter, r *http.Request)
 	}
 	err = json.Unmarshal(bytes, &s)
 	if err != nil {
-		f.internalError(err, "Error during unmarshalling request", w, r)
+		f.InternalError(err, "Error during unmarshalling request", w, r)
 		return
 	}
 	if s.User.ID == "" {
@@ -256,7 +256,7 @@ func (f *KeystoneAPIFixture) CreateUser(w http.ResponseWriter, r *http.Request)
 
 	bytes, err = json.Marshal(&s)
 	if err != nil {
-		f.internalError(err, "Error during marshalling response", w, r)
+		f.InternalError(err, "Error during marshalling response", w, r)
 		return
 	}
 	w.Header().Add("Content-Type", "application/json")
@@ -266,14 +266,14 @@ func (f *KeystoneAPIFixture) CreateUser(w http.ResponseWriter, r *http.Request)
 
 // HandleDomains handles the happy path of GET /v3/domains and POST /v3/domains API
 func (f *KeystoneAPIFixture) HandleDomains(w http.ResponseWriter, r *http.Request) {
-	f.logRequest(r)
+	f.LogRequest(r)
 	switch r.Method {
 	case "GET":
 		f.GetDomains(w, r)
 	case "POST":
 		f.CreateDomain(w, r)
 	default:
-		f.unexpectedRequest(w, r)
+		f.UnexpectedRequest(w, r)
 		return
 	}
 }
@@ -299,7 +299,7 @@ func (f *KeystoneAPIFixture) GetDomains(w http.ResponseWriter, r *http.Request)
 
 	bytes, err := json.Marshal(&s)
 	if err != nil {
-		f.internalError(err, "Error during marshalling response", w, r)
+		f.InternalError(err, "Error during marshalling response", w, r)
 		return
 	}
 	w.Header().Add("Content-Type", "application/json")
@@ -311,7 +311,7 @@ func (f *KeystoneAPIFixture) GetDomains(w http.ResponseWriter, r *http.Request)
 func (f *KeystoneAPIFixture) CreateDomain(w http.ResponseWriter, r *http.Request) {
 	bytes, err := io.ReadAll(r.Body)
 	if err != nil {
-		f.internalError(err, "Error reading request body", w, r)
+		f.InternalError(err, "Error reading request body", w, r)
 		return
 	}
 	var s struct {
@@ -319,7 +319,7 @@ func (f *KeystoneAPIFixture) CreateDomain(w http.ResponseWriter, r *http.Request
 	}
 	err = json.Unmarshal(bytes, &s)
 	if err != nil {
-		f.internalError(err, "Error during unmarshalling request", w, r)
+		f.InternalError(err, "Error during unmarshalling request", w, r)
 		return
 	}
 	if s.Domain.ID == "" {
@@ -330,7 +330,7 @@ func (f *KeystoneAPIFixture) CreateDomain(w http.ResponseWriter, r *http.Request
 
 	bytes, err = json.Marshal(&s)
 	if err != nil {
-		f.internalError(err, "Error during marshalling response", w, r)
+		f.InternalError(err, "Error during marshalling response", w, r)
 		return
 	}
 	w.Header().Add("Content-Type", "application/json")
diff --git a/modules/test/apis/server.go b/modules/test/apis/server.go
index 37dfcbb3..22e7da07 100644
--- a/modules/test/apis/server.go
+++ b/modules/test/apis/server.go
@@ -43,6 +43,12 @@ func (s *FakeAPIServer) Setup(log logr.Logger) {
 	s.mux.HandleFunc("/", s.fallbackHandler)
 }
 
+// AddHandlers adds a function to be called if a request is received for the URL
+// matching the pattern
+func (s *FakeAPIServer) AddHandler(pattern string, handler func(http.ResponseWriter, *http.Request)) {
+	s.mux.HandleFunc(pattern, handler)
+}
+
 func (s *FakeAPIServer) fallbackHandler(w http.ResponseWriter, r *http.Request) {
 	if r == nil {
 		s.log.Info("Unexpected OpenStackAPI nil request")