diff --git a/cmd/web.go b/cmd/web.go
index da6c987ff8..3a46b90911 100644
--- a/cmd/web.go
+++ b/cmd/web.go
@@ -191,7 +191,7 @@ func runWeb(ctx *cli.Context) error {
 	}
 
 	// Set up Chi routes
-	c := routers.NormalRoutes(graceful.GetManager().HammerContext())
+	c := routers.NormalRoutes()
 	err := listen(c, true)
 	<-graceful.GetManager().Done()
 	log.Info("PID: %d Gitea Web Finished", os.Getpid())
diff --git a/modules/context/api.go b/modules/context/api.go
index 092ad73f31..3c4d020413 100644
--- a/modules/context/api.go
+++ b/modules/context/api.go
@@ -20,6 +20,8 @@ import (
 	"code.gitea.io/gitea/modules/httpcache"
 	"code.gitea.io/gitea/modules/log"
 	"code.gitea.io/gitea/modules/setting"
+	"code.gitea.io/gitea/modules/web"
+	web_types "code.gitea.io/gitea/modules/web/types"
 
 	"gitea.com/go-chi/cache"
 )
@@ -41,6 +43,12 @@ type APIContext struct {
 	Package *Package
 }
 
+func init() {
+	web.RegisterResponseStatusProvider[*APIContext](func(req *http.Request) web_types.ResponseStatusProvider {
+		return req.Context().Value(apiContextKey).(*APIContext)
+	})
+}
+
 // Currently, we have the following common fields in error response:
 // * message: the message for end users (it shouldn't be used for error type detection)
 //            if we need to indicate some errors, we should introduce some new fields like ErrorCode or ErrorType
diff --git a/modules/context/base.go b/modules/context/base.go
index c8238050f9..45f33feb08 100644
--- a/modules/context/base.go
+++ b/modules/context/base.go
@@ -96,7 +96,11 @@ func (b *Base) SetTotalCountHeader(total int64) {
 
 // Written returns true if there are something sent to web browser
 func (b *Base) Written() bool {
-	return b.Resp.Status() > 0
+	return b.Resp.WrittenStatus() != 0
+}
+
+func (b *Base) WrittenStatus() int {
+	return b.Resp.WrittenStatus()
 }
 
 // Status writes status code
diff --git a/modules/context/context.go b/modules/context/context.go
index 9e351432c4..93d448fca5 100644
--- a/modules/context/context.go
+++ b/modules/context/context.go
@@ -21,7 +21,9 @@ import (
 	"code.gitea.io/gitea/modules/setting"
 	"code.gitea.io/gitea/modules/templates"
 	"code.gitea.io/gitea/modules/translation"
+	"code.gitea.io/gitea/modules/web"
 	"code.gitea.io/gitea/modules/web/middleware"
+	web_types "code.gitea.io/gitea/modules/web/types"
 
 	"gitea.com/go-chi/cache"
 	"gitea.com/go-chi/session"
@@ -58,6 +60,12 @@ type Context struct {
 	Package *Package
 }
 
+func init() {
+	web.RegisterResponseStatusProvider[*Context](func(req *http.Request) web_types.ResponseStatusProvider {
+		return req.Context().Value(WebContextKey).(*Context)
+	})
+}
+
 // TrHTMLEscapeArgs runs ".Locale.Tr()" but pre-escapes all arguments with html.EscapeString.
 // This is useful if the locale message is intended to only produce HTML content.
 func (ctx *Context) TrHTMLEscapeArgs(msg string, args ...string) string {
diff --git a/modules/context/private.go b/modules/context/private.go
index 41ca8a4709..2e9b31140a 100644
--- a/modules/context/private.go
+++ b/modules/context/private.go
@@ -11,6 +11,8 @@ import (
 
 	"code.gitea.io/gitea/modules/graceful"
 	"code.gitea.io/gitea/modules/process"
+	"code.gitea.io/gitea/modules/web"
+	web_types "code.gitea.io/gitea/modules/web/types"
 )
 
 // PrivateContext represents a context for private routes
@@ -21,6 +23,12 @@ type PrivateContext struct {
 	Repo *Repository
 }
 
+func init() {
+	web.RegisterResponseStatusProvider[*PrivateContext](func(req *http.Request) web_types.ResponseStatusProvider {
+		return req.Context().Value(privateContextKey).(*PrivateContext)
+	})
+}
+
 // Deadline is part of the interface for context.Context and we pass this to the request context
 func (ctx *PrivateContext) Deadline() (deadline time.Time, ok bool) {
 	if ctx.Override != nil {
diff --git a/modules/context/response.go b/modules/context/response.go
index 8708d77da0..2f271f211b 100644
--- a/modules/context/response.go
+++ b/modules/context/response.go
@@ -5,15 +5,20 @@ package context
 
 import (
 	"net/http"
+
+	web_types "code.gitea.io/gitea/modules/web/types"
 )
 
 // ResponseWriter represents a response writer for HTTP
 type ResponseWriter interface {
 	http.ResponseWriter
 	http.Flusher
-	Status() int
+	web_types.ResponseStatusProvider
+
 	Before(func(ResponseWriter))
-	Size() int // used by access logger template
+
+	Status() int // used by access logger template
+	Size() int   // used by access logger template
 }
 
 var _ ResponseWriter = &Response{}
@@ -46,6 +51,10 @@ func (r *Response) Write(bs []byte) (int, error) {
 	return size, nil
 }
 
+func (r *Response) Status() int {
+	return r.status
+}
+
 func (r *Response) Size() int {
 	return r.written
 }
@@ -71,8 +80,8 @@ func (r *Response) Flush() {
 	}
 }
 
-// Status returned status code written
-func (r *Response) Status() int {
+// WrittenStatus returned status code written
+func (r *Response) WrittenStatus() int {
 	return r.status
 }
 
diff --git a/modules/test/context_tests.go b/modules/test/context_tests.go
index 349c7e3e80..cf8af32fc6 100644
--- a/modules/test/context_tests.go
+++ b/modules/test/context_tests.go
@@ -9,6 +9,7 @@ import (
 	"net/http"
 	"net/http/httptest"
 	"net/url"
+	"strings"
 	"testing"
 
 	access_model "code.gitea.io/gitea/models/perm/access"
@@ -25,19 +26,26 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
-// MockContext mock context for unit tests
-// TODO: move this function to other packages, because it depends on "models" package
-func MockContext(t *testing.T, path string) *context.Context {
-	resp := httptest.NewRecorder()
+func mockRequest(t *testing.T, reqPath string) *http.Request {
+	method, path, found := strings.Cut(reqPath, " ")
+	if !found {
+		method = "GET"
+		path = reqPath
+	}
 	requestURL, err := url.Parse(path)
 	assert.NoError(t, err)
-	req := &http.Request{
-		URL:  requestURL,
-		Form: url.Values{},
-	}
+	req := &http.Request{Method: method, URL: requestURL, Form: url.Values{}}
+	req = req.WithContext(middleware.WithContextData(req.Context()))
+	return req
+}
 
+// MockContext mock context for unit tests
+// TODO: move this function to other packages, because it depends on "models" package
+func MockContext(t *testing.T, reqPath string) (*context.Context, *httptest.ResponseRecorder) {
+	resp := httptest.NewRecorder()
+	req := mockRequest(t, reqPath)
 	base, baseCleanUp := context.NewBaseContext(resp, req)
-	base.Data = middleware.ContextData{}
+	base.Data = middleware.GetContextData(req.Context())
 	base.Locale = &translation.MockLocale{}
 	ctx := &context.Context{
 		Base:   base,
@@ -48,29 +56,23 @@ func MockContext(t *testing.T, path string) *context.Context {
 
 	chiCtx := chi.NewRouteContext()
 	ctx.Base.AppendContextValue(chi.RouteCtxKey, chiCtx)
-	return ctx
+	return ctx, resp
 }
 
 // MockAPIContext mock context for unit tests
 // TODO: move this function to other packages, because it depends on "models" package
-func MockAPIContext(t *testing.T, path string) *context.APIContext {
+func MockAPIContext(t *testing.T, reqPath string) (*context.APIContext, *httptest.ResponseRecorder) {
 	resp := httptest.NewRecorder()
-	requestURL, err := url.Parse(path)
-	assert.NoError(t, err)
-	req := &http.Request{
-		URL:  requestURL,
-		Form: url.Values{},
-	}
-
+	req := mockRequest(t, reqPath)
 	base, baseCleanUp := context.NewBaseContext(resp, req)
-	base.Data = middleware.ContextData{}
+	base.Data = middleware.GetContextData(req.Context())
 	base.Locale = &translation.MockLocale{}
 	ctx := &context.APIContext{Base: base}
 	_ = baseCleanUp // during test, it doesn't need to do clean up. TODO: this can be improved later
 
 	chiCtx := chi.NewRouteContext()
 	ctx.Base.AppendContextValue(chi.RouteCtxKey, chiCtx)
-	return ctx
+	return ctx, resp
 }
 
 // LoadRepo load a repo into a test context.
diff --git a/modules/web/handler.go b/modules/web/handler.go
index c8aebd9051..26b7428016 100644
--- a/modules/web/handler.go
+++ b/modules/web/handler.go
@@ -9,25 +9,15 @@ import (
 	"net/http"
 	"reflect"
 
-	"code.gitea.io/gitea/modules/context"
 	"code.gitea.io/gitea/modules/log"
 	"code.gitea.io/gitea/modules/web/routing"
+	"code.gitea.io/gitea/modules/web/types"
 )
 
-// ResponseStatusProvider is an interface to check whether the response has been written by the handler
-type ResponseStatusProvider interface {
-	Written() bool
-}
+var responseStatusProviders = map[reflect.Type]func(req *http.Request) types.ResponseStatusProvider{}
 
-// TODO: decouple this from the context package, let the context package register these providers
-var argTypeProvider = map[reflect.Type]func(req *http.Request) ResponseStatusProvider{
-	reflect.TypeOf(&context.APIContext{}):     func(req *http.Request) ResponseStatusProvider { return context.GetAPIContext(req) },
-	reflect.TypeOf(&context.Context{}):        func(req *http.Request) ResponseStatusProvider { return context.GetWebContext(req) },
-	reflect.TypeOf(&context.PrivateContext{}): func(req *http.Request) ResponseStatusProvider { return context.GetPrivateContext(req) },
-}
-
-func RegisterHandleTypeProvider[T any](fn func(req *http.Request) ResponseStatusProvider) {
-	argTypeProvider[reflect.TypeOf((*T)(nil)).Elem()] = fn
+func RegisterResponseStatusProvider[T any](fn func(req *http.Request) types.ResponseStatusProvider) {
+	responseStatusProviders[reflect.TypeOf((*T)(nil)).Elem()] = fn
 }
 
 // responseWriter is a wrapper of http.ResponseWriter, to check whether the response has been written
@@ -36,10 +26,10 @@ type responseWriter struct {
 	status     int
 }
 
-var _ ResponseStatusProvider = (*responseWriter)(nil)
+var _ types.ResponseStatusProvider = (*responseWriter)(nil)
 
-func (r *responseWriter) Written() bool {
-	return r.status > 0
+func (r *responseWriter) WrittenStatus() int {
+	return r.status
 }
 
 func (r *responseWriter) Header() http.Header {
@@ -68,7 +58,7 @@ var (
 func preCheckHandler(fn reflect.Value, argsIn []reflect.Value) {
 	hasStatusProvider := false
 	for _, argIn := range argsIn {
-		if _, hasStatusProvider = argIn.Interface().(ResponseStatusProvider); hasStatusProvider {
+		if _, hasStatusProvider = argIn.Interface().(types.ResponseStatusProvider); hasStatusProvider {
 			break
 		}
 	}
@@ -101,7 +91,7 @@ func prepareHandleArgsIn(resp http.ResponseWriter, req *http.Request, fn reflect
 		case httpReqType:
 			argsIn[i] = reflect.ValueOf(req)
 		default:
-			if argFn, ok := argTypeProvider[argTyp]; ok {
+			if argFn, ok := responseStatusProviders[argTyp]; ok {
 				if isPreCheck {
 					argsIn[i] = reflect.ValueOf(&responseWriter{})
 				} else {
@@ -129,8 +119,8 @@ func handleResponse(fn reflect.Value, ret []reflect.Value) goctx.CancelFunc {
 
 func hasResponseBeenWritten(argsIn []reflect.Value) bool {
 	for _, argIn := range argsIn {
-		if statusProvider, ok := argIn.Interface().(ResponseStatusProvider); ok {
-			if statusProvider.Written() {
+		if statusProvider, ok := argIn.Interface().(types.ResponseStatusProvider); ok {
+			if statusProvider.WrittenStatus() != 0 {
 				return true
 			}
 		}
@@ -161,7 +151,7 @@ func toHandlerProvider(handler any) func(next http.Handler) http.Handler {
 		return http.HandlerFunc(func(respOrig http.ResponseWriter, req *http.Request) {
 			// wrap the response writer to check whether the response has been written
 			resp := respOrig
-			if _, ok := resp.(ResponseStatusProvider); !ok {
+			if _, ok := resp.(types.ResponseStatusProvider); !ok {
 				resp = &responseWriter{respWriter: resp}
 			}
 
diff --git a/modules/web/middleware/data.go b/modules/web/middleware/data.go
index c1f0516d7d..9497dc02e2 100644
--- a/modules/web/middleware/data.go
+++ b/modules/web/middleware/data.go
@@ -17,7 +17,7 @@ type ContextDataStore interface {
 
 type ContextData map[string]any
 
-func (ds ContextData) GetData() map[string]any {
+func (ds ContextData) GetData() ContextData {
 	return ds
 }
 
diff --git a/modules/web/route.go b/modules/web/route.go
index d801f1025c..db511aeb18 100644
--- a/modules/web/route.go
+++ b/modules/web/route.go
@@ -7,31 +7,31 @@ import (
 	"net/http"
 	"strings"
 
-	"code.gitea.io/gitea/modules/context"
 	"code.gitea.io/gitea/modules/web/middleware"
 
 	"gitea.com/go-chi/binding"
-	chi "github.com/go-chi/chi/v5"
+	"github.com/go-chi/chi/v5"
 )
 
-// Bind binding an obj to a handler
-func Bind[T any](_ T) any {
-	return func(ctx *context.Context) {
+// Bind binding an obj to a handler's context data
+func Bind[T any](_ T) http.HandlerFunc {
+	return func(resp http.ResponseWriter, req *http.Request) {
 		theObj := new(T) // create a new form obj for every request but not use obj directly
-		binding.Bind(ctx.Req, theObj)
-		SetForm(ctx, theObj)
-		middleware.AssignForm(theObj, ctx.Data)
+		data := middleware.GetContextData(req.Context())
+		binding.Bind(req, theObj)
+		SetForm(data, theObj)
+		middleware.AssignForm(theObj, data)
 	}
 }
 
 // SetForm set the form object
-func SetForm(data middleware.ContextDataStore, obj interface{}) {
-	data.GetData()["__form"] = obj
+func SetForm(dataStore middleware.ContextDataStore, obj interface{}) {
+	dataStore.GetData()["__form"] = obj
 }
 
 // GetForm returns the validate form information
-func GetForm(data middleware.ContextDataStore) interface{} {
-	return data.GetData()["__form"]
+func GetForm(dataStore middleware.ContextDataStore) interface{} {
+	return dataStore.GetData()["__form"]
 }
 
 // Route defines a route based on chi's router
diff --git a/modules/web/routing/logger.go b/modules/web/routing/logger.go
index b58065aa73..6a4dae66f7 100644
--- a/modules/web/routing/logger.go
+++ b/modules/web/routing/logger.go
@@ -8,8 +8,8 @@ import (
 	"strings"
 	"time"
 
-	"code.gitea.io/gitea/modules/context"
 	"code.gitea.io/gitea/modules/log"
+	"code.gitea.io/gitea/modules/web/types"
 )
 
 // NewLoggerHandler is a handler that will log routing to the router log taking account of
@@ -86,8 +86,8 @@ func logPrinter(logger log.Logger) func(trigger Event, record *requestRecord) {
 		}
 
 		var status int
-		if v, ok := record.responseWriter.(context.ResponseWriter); ok {
-			status = v.Status()
+		if v, ok := record.responseWriter.(types.ResponseStatusProvider); ok {
+			status = v.WrittenStatus()
 		}
 		logf := log.Info
 		if strings.HasPrefix(req.RequestURI, "/assets/") {
diff --git a/modules/web/types/response.go b/modules/web/types/response.go
new file mode 100644
index 0000000000..834f4912f4
--- /dev/null
+++ b/modules/web/types/response.go
@@ -0,0 +1,10 @@
+// Copyright 2023 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package types
+
+// ResponseStatusProvider is an interface to get the written status in the response
+// Many packages need this interface, so put it in the separate package to avoid import cycle
+type ResponseStatusProvider interface {
+	WrittenStatus() int
+}
diff --git a/routers/api/actions/actions.go b/routers/api/actions/actions.go
index bdcac41206..a418b3a1c4 100644
--- a/routers/api/actions/actions.go
+++ b/routers/api/actions/actions.go
@@ -4,7 +4,6 @@
 package actions
 
 import (
-	"context"
 	"net/http"
 
 	"code.gitea.io/gitea/modules/web"
@@ -12,7 +11,7 @@ import (
 	"code.gitea.io/gitea/routers/api/actions/runner"
 )
 
-func Routes(_ context.Context, prefix string) *web.Route {
+func Routes(prefix string) *web.Route {
 	m := web.NewRoute()
 
 	path, handler := ping.NewPingServiceHandler()
diff --git a/routers/api/actions/artifacts.go b/routers/api/actions/artifacts.go
index 4b10cd7ad1..060f7bc3d4 100644
--- a/routers/api/actions/artifacts.go
+++ b/routers/api/actions/artifacts.go
@@ -82,6 +82,7 @@ import (
 	"code.gitea.io/gitea/modules/storage"
 	"code.gitea.io/gitea/modules/util"
 	"code.gitea.io/gitea/modules/web"
+	web_types "code.gitea.io/gitea/modules/web/types"
 )
 
 const (
@@ -102,7 +103,7 @@ type ArtifactContext struct {
 }
 
 func init() {
-	web.RegisterHandleTypeProvider[*ArtifactContext](func(req *http.Request) web.ResponseStatusProvider {
+	web.RegisterResponseStatusProvider[*ArtifactContext](func(req *http.Request) web_types.ResponseStatusProvider {
 		return req.Context().Value(artifactContextKey).(*ArtifactContext)
 	})
 }
diff --git a/routers/api/packages/api.go b/routers/api/packages/api.go
index 4f0f637fa5..fa7f66f3ab 100644
--- a/routers/api/packages/api.go
+++ b/routers/api/packages/api.go
@@ -4,7 +4,6 @@
 package packages
 
 import (
-	gocontext "context"
 	"net/http"
 	"regexp"
 	"strings"
@@ -96,7 +95,7 @@ func verifyAuth(r *web.Route, authMethods []auth.Method) {
 
 // CommonRoutes provide endpoints for most package managers (except containers - see below)
 // These are mounted on `/api/packages` (not `/api/v1/packages`)
-func CommonRoutes(ctx gocontext.Context) *web.Route {
+func CommonRoutes() *web.Route {
 	r := web.NewRoute()
 
 	r.Use(context.PackageContexter())
@@ -590,7 +589,7 @@ func CommonRoutes(ctx gocontext.Context) *web.Route {
 // ContainerRoutes provides endpoints that implement the OCI API to serve containers
 // These have to be mounted on `/v2/...` to comply with the OCI spec:
 // https://github.com/opencontainers/distribution-spec/blob/main/spec.md
-func ContainerRoutes(ctx gocontext.Context) *web.Route {
+func ContainerRoutes() *web.Route {
 	r := web.NewRoute()
 
 	r.Use(context.PackageContexter())
diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go
index 37361a8b96..be66cc5240 100644
--- a/routers/api/v1/api.go
+++ b/routers/api/v1/api.go
@@ -64,7 +64,6 @@
 package v1
 
 import (
-	gocontext "context"
 	"fmt"
 	"net/http"
 	"strings"
@@ -705,7 +704,7 @@ func buildAuthGroup() *auth.Group {
 }
 
 // Routes registers all v1 APIs routes to web application.
-func Routes(ctx gocontext.Context) *web.Route {
+func Routes() *web.Route {
 	m := web.NewRoute()
 
 	m.Use(securityHeaders())
@@ -722,13 +721,8 @@ func Routes(ctx gocontext.Context) *web.Route {
 	}
 	m.Use(context.APIContexter())
 
-	group := buildAuthGroup()
-	if err := group.Init(ctx); err != nil {
-		log.Error("Could not initialize '%s' auth method, error: %s", group.Name(), err)
-	}
-
 	// Get user from session if logged in.
-	m.Use(auth.APIAuth(group))
+	m.Use(auth.APIAuth(buildAuthGroup()))
 
 	m.Use(auth.VerifyAuthWithOptionsAPI(&auth.VerifyOptions{
 		SignInRequired: setting.Service.RequireSignInView,
diff --git a/routers/api/v1/misc/markup_test.go b/routers/api/v1/misc/markup_test.go
index fdf540fd65..bab06b3e66 100644
--- a/routers/api/v1/misc/markup_test.go
+++ b/routers/api/v1/misc/markup_test.go
@@ -7,18 +7,14 @@ import (
 	go_context "context"
 	"io"
 	"net/http"
-	"net/http/httptest"
-	"net/url"
 	"strings"
 	"testing"
 
-	"code.gitea.io/gitea/modules/context"
 	"code.gitea.io/gitea/modules/markup"
 	"code.gitea.io/gitea/modules/setting"
 	api "code.gitea.io/gitea/modules/structs"
-	"code.gitea.io/gitea/modules/util"
+	"code.gitea.io/gitea/modules/test"
 	"code.gitea.io/gitea/modules/web"
-	"code.gitea.io/gitea/modules/web/middleware"
 
 	"github.com/stretchr/testify/assert"
 )
@@ -29,34 +25,16 @@ const (
 	AppSubURL = AppURL + Repo + "/"
 )
 
-func createAPIContext(req *http.Request) (*context.APIContext, *httptest.ResponseRecorder) {
-	resp := httptest.NewRecorder()
-	base, baseCleanUp := context.NewBaseContext(resp, req)
-	base.Data = middleware.ContextData{}
-	c := &context.APIContext{Base: base}
-	_ = baseCleanUp // during test, it doesn't need to do clean up. TODO: this can be improved later
-
-	return c, resp
-}
-
 func testRenderMarkup(t *testing.T, mode, filePath, text, responseBody string, responseCode int) {
 	setting.AppURL = AppURL
-
 	options := api.MarkupOption{
 		Mode:     mode,
-		Text:     "",
+		Text:     text,
 		Context:  Repo,
 		Wiki:     true,
 		FilePath: filePath,
 	}
-	requrl, _ := url.Parse(util.URLJoin(AppURL, "api", "v1", "markup"))
-	req := &http.Request{
-		Method: "POST",
-		URL:    requrl,
-	}
-	ctx, resp := createAPIContext(req)
-
-	options.Text = text
+	ctx, resp := test.MockAPIContext(t, "POST /api/v1/markup")
 	web.SetForm(ctx, &options)
 	Markup(ctx)
 	assert.Equal(t, responseBody, resp.Body.String())
@@ -66,21 +44,13 @@ func testRenderMarkup(t *testing.T, mode, filePath, text, responseBody string, r
 
 func testRenderMarkdown(t *testing.T, mode, text, responseBody string, responseCode int) {
 	setting.AppURL = AppURL
-
 	options := api.MarkdownOption{
 		Mode:    mode,
-		Text:    "",
+		Text:    text,
 		Context: Repo,
 		Wiki:    true,
 	}
-	requrl, _ := url.Parse(util.URLJoin(AppURL, "api", "v1", "markdown"))
-	req := &http.Request{
-		Method: "POST",
-		URL:    requrl,
-	}
-	ctx, resp := createAPIContext(req)
-
-	options.Text = text
+	ctx, resp := test.MockAPIContext(t, "POST /api/v1/markdown")
 	web.SetForm(ctx, &options)
 	Markdown(ctx)
 	assert.Equal(t, responseBody, resp.Body.String())
@@ -187,19 +157,12 @@ var simpleCases = []string{
 
 func TestAPI_RenderSimple(t *testing.T) {
 	setting.AppURL = AppURL
-
 	options := api.MarkdownOption{
 		Mode:    "markdown",
 		Text:    "",
 		Context: Repo,
 	}
-	requrl, _ := url.Parse(util.URLJoin(AppURL, "api", "v1", "markdown"))
-	req := &http.Request{
-		Method: "POST",
-		URL:    requrl,
-	}
-	ctx, resp := createAPIContext(req)
-
+	ctx, resp := test.MockAPIContext(t, "POST /api/v1/markdown")
 	for i := 0; i < len(simpleCases); i += 2 {
 		options.Text = simpleCases[i]
 		web.SetForm(ctx, &options)
@@ -211,14 +174,7 @@ func TestAPI_RenderSimple(t *testing.T) {
 
 func TestAPI_RenderRaw(t *testing.T) {
 	setting.AppURL = AppURL
-
-	requrl, _ := url.Parse(util.URLJoin(AppURL, "api", "v1", "markdown"))
-	req := &http.Request{
-		Method: "POST",
-		URL:    requrl,
-	}
-	ctx, resp := createAPIContext(req)
-
+	ctx, resp := test.MockAPIContext(t, "POST /api/v1/markdown")
 	for i := 0; i < len(simpleCases); i += 2 {
 		ctx.Req.Body = io.NopCloser(strings.NewReader(simpleCases[i]))
 		MarkdownRaw(ctx)
diff --git a/routers/api/v1/repo/hook_test.go b/routers/api/v1/repo/hook_test.go
index 56658b45d5..b43a22cd55 100644
--- a/routers/api/v1/repo/hook_test.go
+++ b/routers/api/v1/repo/hook_test.go
@@ -17,7 +17,7 @@ import (
 func TestTestHook(t *testing.T) {
 	unittest.PrepareTestEnv(t)
 
-	ctx := test.MockAPIContext(t, "user2/repo1/wiki/_pages")
+	ctx, _ := test.MockAPIContext(t, "user2/repo1/wiki/_pages")
 	ctx.SetParams(":id", "1")
 	test.LoadRepo(t, ctx, 1)
 	test.LoadRepoCommit(t, ctx)
diff --git a/routers/api/v1/repo/repo_test.go b/routers/api/v1/repo/repo_test.go
index e1bdea5c82..7593a87c2c 100644
--- a/routers/api/v1/repo/repo_test.go
+++ b/routers/api/v1/repo/repo_test.go
@@ -19,7 +19,7 @@ import (
 func TestRepoEdit(t *testing.T) {
 	unittest.PrepareTestEnv(t)
 
-	ctx := test.MockAPIContext(t, "user2/repo1")
+	ctx, _ := test.MockAPIContext(t, "user2/repo1")
 	test.LoadRepo(t, ctx, 1)
 	test.LoadUser(t, ctx, 2)
 	ctx.Repo.Owner = ctx.Doer
@@ -65,7 +65,7 @@ func TestRepoEdit(t *testing.T) {
 func TestRepoEditNameChange(t *testing.T) {
 	unittest.PrepareTestEnv(t)
 
-	ctx := test.MockAPIContext(t, "user2/repo1")
+	ctx, _ := test.MockAPIContext(t, "user2/repo1")
 	test.LoadRepo(t, ctx, 1)
 	test.LoadUser(t, ctx, 2)
 	ctx.Repo.Owner = ctx.Doer
diff --git a/routers/init.go b/routers/init.go
index 725e5c52ba..54e8d2b8b3 100644
--- a/routers/init.go
+++ b/routers/init.go
@@ -174,27 +174,27 @@ func GlobalInitInstalled(ctx context.Context) {
 }
 
 // NormalRoutes represents non install routes
-func NormalRoutes(ctx context.Context) *web.Route {
+func NormalRoutes() *web.Route {
 	_ = templates.HTMLRenderer()
 	r := web.NewRoute()
 	r.Use(common.ProtocolMiddlewares()...)
 
-	r.Mount("/", web_routers.Routes(ctx))
-	r.Mount("/api/v1", apiv1.Routes(ctx))
+	r.Mount("/", web_routers.Routes())
+	r.Mount("/api/v1", apiv1.Routes())
 	r.Mount("/api/internal", private.Routes())
 
 	r.Post("/-/fetch-redirect", common.FetchRedirectDelegate)
 
 	if setting.Packages.Enabled {
 		// This implements package support for most package managers
-		r.Mount("/api/packages", packages_router.CommonRoutes(ctx))
+		r.Mount("/api/packages", packages_router.CommonRoutes())
 		// This implements the OCI API (Note this is not preceded by /api but is instead /v2)
-		r.Mount("/v2", packages_router.ContainerRoutes(ctx))
+		r.Mount("/v2", packages_router.ContainerRoutes())
 	}
 
 	if setting.Actions.Enabled {
 		prefix := "/api/actions"
-		r.Mount(prefix, actions_router.Routes(ctx, prefix))
+		r.Mount(prefix, actions_router.Routes(prefix))
 
 		// TODO: Pipeline api used for runner internal communication with gitea server. but only artifact is used for now.
 		// In Github, it uses ACTIONS_RUNTIME_URL=https://pipelines.actions.githubusercontent.com/fLgcSHkPGySXeIFrg8W8OBSfeg3b5Fls1A1CwX566g8PayEGlg/
diff --git a/routers/web/admin/users_test.go b/routers/web/admin/users_test.go
index ed58a54eef..19d6d7294d 100644
--- a/routers/web/admin/users_test.go
+++ b/routers/web/admin/users_test.go
@@ -19,7 +19,7 @@ import (
 
 func TestNewUserPost_MustChangePassword(t *testing.T) {
 	unittest.PrepareTestEnv(t)
-	ctx := test.MockContext(t, "admin/users/new")
+	ctx, _ := test.MockContext(t, "admin/users/new")
 
 	u := unittest.AssertExistsAndLoadBean(t, &user_model.User{
 		IsAdmin: true,
@@ -56,7 +56,7 @@ func TestNewUserPost_MustChangePassword(t *testing.T) {
 
 func TestNewUserPost_MustChangePasswordFalse(t *testing.T) {
 	unittest.PrepareTestEnv(t)
-	ctx := test.MockContext(t, "admin/users/new")
+	ctx, _ := test.MockContext(t, "admin/users/new")
 
 	u := unittest.AssertExistsAndLoadBean(t, &user_model.User{
 		IsAdmin: true,
@@ -93,7 +93,7 @@ func TestNewUserPost_MustChangePasswordFalse(t *testing.T) {
 
 func TestNewUserPost_InvalidEmail(t *testing.T) {
 	unittest.PrepareTestEnv(t)
-	ctx := test.MockContext(t, "admin/users/new")
+	ctx, _ := test.MockContext(t, "admin/users/new")
 
 	u := unittest.AssertExistsAndLoadBean(t, &user_model.User{
 		IsAdmin: true,
@@ -123,7 +123,7 @@ func TestNewUserPost_InvalidEmail(t *testing.T) {
 
 func TestNewUserPost_VisibilityDefaultPublic(t *testing.T) {
 	unittest.PrepareTestEnv(t)
-	ctx := test.MockContext(t, "admin/users/new")
+	ctx, _ := test.MockContext(t, "admin/users/new")
 
 	u := unittest.AssertExistsAndLoadBean(t, &user_model.User{
 		IsAdmin: true,
@@ -161,7 +161,7 @@ func TestNewUserPost_VisibilityDefaultPublic(t *testing.T) {
 
 func TestNewUserPost_VisibilityPrivate(t *testing.T) {
 	unittest.PrepareTestEnv(t)
-	ctx := test.MockContext(t, "admin/users/new")
+	ctx, _ := test.MockContext(t, "admin/users/new")
 
 	u := unittest.AssertExistsAndLoadBean(t, &user_model.User{
 		IsAdmin: true,
diff --git a/routers/web/org/projects_test.go b/routers/web/org/projects_test.go
index 3450fa8e72..08a97b7d2d 100644
--- a/routers/web/org/projects_test.go
+++ b/routers/web/org/projects_test.go
@@ -15,7 +15,7 @@ import (
 
 func TestCheckProjectBoardChangePermissions(t *testing.T) {
 	unittest.PrepareTestEnv(t)
-	ctx := test.MockContext(t, "user2/-/projects/4/4")
+	ctx, _ := test.MockContext(t, "user2/-/projects/4/4")
 	test.LoadUser(t, ctx, 2)
 	ctx.ContextUser = ctx.Doer // user2
 	ctx.SetParams(":id", "4")
diff --git a/routers/web/repo/editor_test.go b/routers/web/repo/editor_test.go
index 1e53aac9b0..52dded68b7 100644
--- a/routers/web/repo/editor_test.go
+++ b/routers/web/repo/editor_test.go
@@ -41,7 +41,7 @@ func TestCleanUploadName(t *testing.T) {
 
 func TestGetUniquePatchBranchName(t *testing.T) {
 	unittest.PrepareTestEnv(t)
-	ctx := test.MockContext(t, "user2/repo1")
+	ctx, _ := test.MockContext(t, "user2/repo1")
 	ctx.SetParams(":id", "1")
 	test.LoadRepo(t, ctx, 1)
 	test.LoadRepoCommit(t, ctx)
@@ -56,7 +56,7 @@ func TestGetUniquePatchBranchName(t *testing.T) {
 
 func TestGetClosestParentWithFiles(t *testing.T) {
 	unittest.PrepareTestEnv(t)
-	ctx := test.MockContext(t, "user2/repo1")
+	ctx, _ := test.MockContext(t, "user2/repo1")
 	ctx.SetParams(":id", "1")
 	test.LoadRepo(t, ctx, 1)
 	test.LoadRepoCommit(t, ctx)
diff --git a/routers/web/repo/issue_label_test.go b/routers/web/repo/issue_label_test.go
index c24fe898b6..4c9a359438 100644
--- a/routers/web/repo/issue_label_test.go
+++ b/routers/web/repo/issue_label_test.go
@@ -32,7 +32,7 @@ func int64SliceToCommaSeparated(a []int64) string {
 func TestInitializeLabels(t *testing.T) {
 	unittest.PrepareTestEnv(t)
 	assert.NoError(t, repository.LoadRepoConfig())
-	ctx := test.MockContext(t, "user2/repo1/labels/initialize")
+	ctx, _ := test.MockContext(t, "user2/repo1/labels/initialize")
 	test.LoadUser(t, ctx, 2)
 	test.LoadRepo(t, ctx, 2)
 	web.SetForm(ctx, &forms.InitializeLabelsForm{TemplateName: "Default"})
@@ -57,7 +57,7 @@ func TestRetrieveLabels(t *testing.T) {
 		{1, "leastissues", []int64{2, 1}},
 		{2, "", []int64{}},
 	} {
-		ctx := test.MockContext(t, "user/repo/issues")
+		ctx, _ := test.MockContext(t, "user/repo/issues")
 		test.LoadUser(t, ctx, 2)
 		test.LoadRepo(t, ctx, testCase.RepoID)
 		ctx.Req.Form.Set("sort", testCase.Sort)
@@ -75,7 +75,7 @@ func TestRetrieveLabels(t *testing.T) {
 
 func TestNewLabel(t *testing.T) {
 	unittest.PrepareTestEnv(t)
-	ctx := test.MockContext(t, "user2/repo1/labels/edit")
+	ctx, _ := test.MockContext(t, "user2/repo1/labels/edit")
 	test.LoadUser(t, ctx, 2)
 	test.LoadRepo(t, ctx, 1)
 	web.SetForm(ctx, &forms.CreateLabelForm{
@@ -93,7 +93,7 @@ func TestNewLabel(t *testing.T) {
 
 func TestUpdateLabel(t *testing.T) {
 	unittest.PrepareTestEnv(t)
-	ctx := test.MockContext(t, "user2/repo1/labels/edit")
+	ctx, _ := test.MockContext(t, "user2/repo1/labels/edit")
 	test.LoadUser(t, ctx, 2)
 	test.LoadRepo(t, ctx, 1)
 	web.SetForm(ctx, &forms.CreateLabelForm{
@@ -113,7 +113,7 @@ func TestUpdateLabel(t *testing.T) {
 
 func TestDeleteLabel(t *testing.T) {
 	unittest.PrepareTestEnv(t)
-	ctx := test.MockContext(t, "user2/repo1/labels/delete")
+	ctx, _ := test.MockContext(t, "user2/repo1/labels/delete")
 	test.LoadUser(t, ctx, 2)
 	test.LoadRepo(t, ctx, 1)
 	ctx.Req.Form.Set("id", "2")
@@ -126,7 +126,7 @@ func TestDeleteLabel(t *testing.T) {
 
 func TestUpdateIssueLabel_Clear(t *testing.T) {
 	unittest.PrepareTestEnv(t)
-	ctx := test.MockContext(t, "user2/repo1/issues/labels")
+	ctx, _ := test.MockContext(t, "user2/repo1/issues/labels")
 	test.LoadUser(t, ctx, 2)
 	test.LoadRepo(t, ctx, 1)
 	ctx.Req.Form.Set("issue_ids", "1,3")
@@ -151,7 +151,7 @@ func TestUpdateIssueLabel_Toggle(t *testing.T) {
 		{"toggle", []int64{1, 2}, 2, true},
 	} {
 		unittest.PrepareTestEnv(t)
-		ctx := test.MockContext(t, "user2/repo1/issues/labels")
+		ctx, _ := test.MockContext(t, "user2/repo1/issues/labels")
 		test.LoadUser(t, ctx, 2)
 		test.LoadRepo(t, ctx, 1)
 		ctx.Req.Form.Set("issue_ids", int64SliceToCommaSeparated(testCase.IssueIDs))
diff --git a/routers/web/repo/projects_test.go b/routers/web/repo/projects_test.go
index c712902ea9..e2797772a8 100644
--- a/routers/web/repo/projects_test.go
+++ b/routers/web/repo/projects_test.go
@@ -14,7 +14,7 @@ import (
 
 func TestCheckProjectBoardChangePermissions(t *testing.T) {
 	unittest.PrepareTestEnv(t)
-	ctx := test.MockContext(t, "user2/repo1/projects/1/2")
+	ctx, _ := test.MockContext(t, "user2/repo1/projects/1/2")
 	test.LoadUser(t, ctx, 2)
 	test.LoadRepo(t, ctx, 1)
 	ctx.SetParams(":id", "1")
diff --git a/routers/web/repo/release_test.go b/routers/web/repo/release_test.go
index 9ec1b4d349..07e349811e 100644
--- a/routers/web/repo/release_test.go
+++ b/routers/web/repo/release_test.go
@@ -47,7 +47,7 @@ func TestNewReleasePost(t *testing.T) {
 	} {
 		unittest.PrepareTestEnv(t)
 
-		ctx := test.MockContext(t, "user2/repo1/releases/new")
+		ctx, _ := test.MockContext(t, "user2/repo1/releases/new")
 		test.LoadUser(t, ctx, 2)
 		test.LoadRepo(t, ctx, 1)
 		test.LoadGitRepo(t, ctx)
@@ -67,7 +67,7 @@ func TestNewReleasePost(t *testing.T) {
 
 func TestNewReleasesList(t *testing.T) {
 	unittest.PrepareTestEnv(t)
-	ctx := test.MockContext(t, "user2/repo-release/releases")
+	ctx, _ := test.MockContext(t, "user2/repo-release/releases")
 	test.LoadUser(t, ctx, 2)
 	test.LoadRepo(t, ctx, 57)
 	test.LoadGitRepo(t, ctx)
diff --git a/routers/web/repo/settings_test.go b/routers/web/repo/settings_test.go
index 3bb202505c..a33e92c821 100644
--- a/routers/web/repo/settings_test.go
+++ b/routers/web/repo/settings_test.go
@@ -42,7 +42,7 @@ func TestAddReadOnlyDeployKey(t *testing.T) {
 	}
 	unittest.PrepareTestEnv(t)
 
-	ctx := test.MockContext(t, "user2/repo1/settings/keys")
+	ctx, _ := test.MockContext(t, "user2/repo1/settings/keys")
 
 	test.LoadUser(t, ctx, 2)
 	test.LoadRepo(t, ctx, 2)
@@ -71,7 +71,7 @@ func TestAddReadWriteOnlyDeployKey(t *testing.T) {
 
 	unittest.PrepareTestEnv(t)
 
-	ctx := test.MockContext(t, "user2/repo1/settings/keys")
+	ctx, _ := test.MockContext(t, "user2/repo1/settings/keys")
 
 	test.LoadUser(t, ctx, 2)
 	test.LoadRepo(t, ctx, 2)
@@ -94,7 +94,7 @@ func TestAddReadWriteOnlyDeployKey(t *testing.T) {
 
 func TestCollaborationPost(t *testing.T) {
 	unittest.PrepareTestEnv(t)
-	ctx := test.MockContext(t, "user2/repo1/issues/labels")
+	ctx, _ := test.MockContext(t, "user2/repo1/issues/labels")
 	test.LoadUser(t, ctx, 2)
 	test.LoadUser(t, ctx, 4)
 	test.LoadRepo(t, ctx, 1)
@@ -129,7 +129,7 @@ func TestCollaborationPost(t *testing.T) {
 
 func TestCollaborationPost_InactiveUser(t *testing.T) {
 	unittest.PrepareTestEnv(t)
-	ctx := test.MockContext(t, "user2/repo1/issues/labels")
+	ctx, _ := test.MockContext(t, "user2/repo1/issues/labels")
 	test.LoadUser(t, ctx, 2)
 	test.LoadUser(t, ctx, 9)
 	test.LoadRepo(t, ctx, 1)
@@ -152,7 +152,7 @@ func TestCollaborationPost_InactiveUser(t *testing.T) {
 
 func TestCollaborationPost_AddCollaboratorTwice(t *testing.T) {
 	unittest.PrepareTestEnv(t)
-	ctx := test.MockContext(t, "user2/repo1/issues/labels")
+	ctx, _ := test.MockContext(t, "user2/repo1/issues/labels")
 	test.LoadUser(t, ctx, 2)
 	test.LoadUser(t, ctx, 4)
 	test.LoadRepo(t, ctx, 1)
@@ -193,7 +193,7 @@ func TestCollaborationPost_AddCollaboratorTwice(t *testing.T) {
 
 func TestCollaborationPost_NonExistentUser(t *testing.T) {
 	unittest.PrepareTestEnv(t)
-	ctx := test.MockContext(t, "user2/repo1/issues/labels")
+	ctx, _ := test.MockContext(t, "user2/repo1/issues/labels")
 	test.LoadUser(t, ctx, 2)
 	test.LoadRepo(t, ctx, 1)
 
@@ -215,7 +215,7 @@ func TestCollaborationPost_NonExistentUser(t *testing.T) {
 
 func TestAddTeamPost(t *testing.T) {
 	unittest.PrepareTestEnv(t)
-	ctx := test.MockContext(t, "org26/repo43")
+	ctx, _ := test.MockContext(t, "org26/repo43")
 
 	ctx.Req.Form.Set("team", "team11")
 
@@ -255,7 +255,7 @@ func TestAddTeamPost(t *testing.T) {
 
 func TestAddTeamPost_NotAllowed(t *testing.T) {
 	unittest.PrepareTestEnv(t)
-	ctx := test.MockContext(t, "org26/repo43")
+	ctx, _ := test.MockContext(t, "org26/repo43")
 
 	ctx.Req.Form.Set("team", "team11")
 
@@ -295,7 +295,7 @@ func TestAddTeamPost_NotAllowed(t *testing.T) {
 
 func TestAddTeamPost_AddTeamTwice(t *testing.T) {
 	unittest.PrepareTestEnv(t)
-	ctx := test.MockContext(t, "org26/repo43")
+	ctx, _ := test.MockContext(t, "org26/repo43")
 
 	ctx.Req.Form.Set("team", "team11")
 
@@ -336,7 +336,7 @@ func TestAddTeamPost_AddTeamTwice(t *testing.T) {
 
 func TestAddTeamPost_NonExistentTeam(t *testing.T) {
 	unittest.PrepareTestEnv(t)
-	ctx := test.MockContext(t, "org26/repo43")
+	ctx, _ := test.MockContext(t, "org26/repo43")
 
 	ctx.Req.Form.Set("team", "team-non-existent")
 
@@ -369,7 +369,7 @@ func TestAddTeamPost_NonExistentTeam(t *testing.T) {
 
 func TestDeleteTeam(t *testing.T) {
 	unittest.PrepareTestEnv(t)
-	ctx := test.MockContext(t, "org3/team1/repo3")
+	ctx, _ := test.MockContext(t, "org3/team1/repo3")
 
 	ctx.Req.Form.Set("id", "2")
 
diff --git a/routers/web/repo/wiki_test.go b/routers/web/repo/wiki_test.go
index e51820a520..d85879d1e5 100644
--- a/routers/web/repo/wiki_test.go
+++ b/routers/web/repo/wiki_test.go
@@ -78,7 +78,7 @@ func assertPagesMetas(t *testing.T, expectedNames []string, metas interface{}) {
 func TestWiki(t *testing.T) {
 	unittest.PrepareTestEnv(t)
 
-	ctx := test.MockContext(t, "user2/repo1/wiki/?action=_pages")
+	ctx, _ := test.MockContext(t, "user2/repo1/wiki/?action=_pages")
 	ctx.SetParams("*", "Home")
 	test.LoadRepo(t, ctx, 1)
 	Wiki(ctx)
@@ -90,7 +90,7 @@ func TestWiki(t *testing.T) {
 func TestWikiPages(t *testing.T) {
 	unittest.PrepareTestEnv(t)
 
-	ctx := test.MockContext(t, "user2/repo1/wiki/?action=_pages")
+	ctx, _ := test.MockContext(t, "user2/repo1/wiki/?action=_pages")
 	test.LoadRepo(t, ctx, 1)
 	WikiPages(ctx)
 	assert.EqualValues(t, http.StatusOK, ctx.Resp.Status())
@@ -100,7 +100,7 @@ func TestWikiPages(t *testing.T) {
 func TestNewWiki(t *testing.T) {
 	unittest.PrepareTestEnv(t)
 
-	ctx := test.MockContext(t, "user2/repo1/wiki/?action=_new")
+	ctx, _ := test.MockContext(t, "user2/repo1/wiki/?action=_new")
 	test.LoadUser(t, ctx, 2)
 	test.LoadRepo(t, ctx, 1)
 	NewWiki(ctx)
@@ -115,7 +115,7 @@ func TestNewWikiPost(t *testing.T) {
 	} {
 		unittest.PrepareTestEnv(t)
 
-		ctx := test.MockContext(t, "user2/repo1/wiki/?action=_new")
+		ctx, _ := test.MockContext(t, "user2/repo1/wiki/?action=_new")
 		test.LoadUser(t, ctx, 2)
 		test.LoadRepo(t, ctx, 1)
 		web.SetForm(ctx, &forms.NewWikiForm{
@@ -133,7 +133,7 @@ func TestNewWikiPost(t *testing.T) {
 func TestNewWikiPost_ReservedName(t *testing.T) {
 	unittest.PrepareTestEnv(t)
 
-	ctx := test.MockContext(t, "user2/repo1/wiki/?action=_new")
+	ctx, _ := test.MockContext(t, "user2/repo1/wiki/?action=_new")
 	test.LoadUser(t, ctx, 2)
 	test.LoadRepo(t, ctx, 1)
 	web.SetForm(ctx, &forms.NewWikiForm{
@@ -150,7 +150,7 @@ func TestNewWikiPost_ReservedName(t *testing.T) {
 func TestEditWiki(t *testing.T) {
 	unittest.PrepareTestEnv(t)
 
-	ctx := test.MockContext(t, "user2/repo1/wiki/Home?action=_edit")
+	ctx, _ := test.MockContext(t, "user2/repo1/wiki/Home?action=_edit")
 	ctx.SetParams("*", "Home")
 	test.LoadUser(t, ctx, 2)
 	test.LoadRepo(t, ctx, 1)
@@ -166,7 +166,7 @@ func TestEditWikiPost(t *testing.T) {
 		"New/<page>",
 	} {
 		unittest.PrepareTestEnv(t)
-		ctx := test.MockContext(t, "user2/repo1/wiki/Home?action=_new")
+		ctx, _ := test.MockContext(t, "user2/repo1/wiki/Home?action=_new")
 		ctx.SetParams("*", "Home")
 		test.LoadUser(t, ctx, 2)
 		test.LoadRepo(t, ctx, 1)
@@ -188,7 +188,7 @@ func TestEditWikiPost(t *testing.T) {
 func TestDeleteWikiPagePost(t *testing.T) {
 	unittest.PrepareTestEnv(t)
 
-	ctx := test.MockContext(t, "user2/repo1/wiki/Home?action=_delete")
+	ctx, _ := test.MockContext(t, "user2/repo1/wiki/Home?action=_delete")
 	test.LoadUser(t, ctx, 2)
 	test.LoadRepo(t, ctx, 1)
 	DeleteWikiPagePost(ctx)
@@ -207,7 +207,7 @@ func TestWikiRaw(t *testing.T) {
 	} {
 		unittest.PrepareTestEnv(t)
 
-		ctx := test.MockContext(t, "user2/repo1/wiki/raw/"+url.PathEscape(filepath))
+		ctx, _ := test.MockContext(t, "user2/repo1/wiki/raw/"+url.PathEscape(filepath))
 		ctx.SetParams("*", filepath)
 		test.LoadUser(t, ctx, 2)
 		test.LoadRepo(t, ctx, 1)
diff --git a/routers/web/user/home_test.go b/routers/web/user/home_test.go
index 534b0b2620..3a06a38c24 100644
--- a/routers/web/user/home_test.go
+++ b/routers/web/user/home_test.go
@@ -20,7 +20,7 @@ func TestArchivedIssues(t *testing.T) {
 	setting.UI.IssuePagingNum = 1
 	assert.NoError(t, unittest.LoadFixtures())
 
-	ctx := test.MockContext(t, "issues")
+	ctx, _ := test.MockContext(t, "issues")
 	test.LoadUser(t, ctx, 30)
 	ctx.Req.Form.Set("state", "open")
 
@@ -53,7 +53,7 @@ func TestIssues(t *testing.T) {
 	setting.UI.IssuePagingNum = 1
 	assert.NoError(t, unittest.LoadFixtures())
 
-	ctx := test.MockContext(t, "issues")
+	ctx, _ := test.MockContext(t, "issues")
 	test.LoadUser(t, ctx, 2)
 	ctx.Req.Form.Set("state", "closed")
 	Issues(ctx)
@@ -69,7 +69,7 @@ func TestPulls(t *testing.T) {
 	setting.UI.IssuePagingNum = 20
 	assert.NoError(t, unittest.LoadFixtures())
 
-	ctx := test.MockContext(t, "pulls")
+	ctx, _ := test.MockContext(t, "pulls")
 	test.LoadUser(t, ctx, 2)
 	ctx.Req.Form.Set("state", "open")
 	Pulls(ctx)
@@ -82,7 +82,7 @@ func TestMilestones(t *testing.T) {
 	setting.UI.IssuePagingNum = 1
 	assert.NoError(t, unittest.LoadFixtures())
 
-	ctx := test.MockContext(t, "milestones")
+	ctx, _ := test.MockContext(t, "milestones")
 	test.LoadUser(t, ctx, 2)
 	ctx.SetParams("sort", "issues")
 	ctx.Req.Form.Set("state", "closed")
@@ -101,7 +101,7 @@ func TestMilestonesForSpecificRepo(t *testing.T) {
 	setting.UI.IssuePagingNum = 1
 	assert.NoError(t, unittest.LoadFixtures())
 
-	ctx := test.MockContext(t, "milestones")
+	ctx, _ := test.MockContext(t, "milestones")
 	test.LoadUser(t, ctx, 2)
 	ctx.SetParams("sort", "issues")
 	ctx.SetParams("repo", "1")
diff --git a/routers/web/user/setting/account_test.go b/routers/web/user/setting/account_test.go
index 569d597722..ba840db288 100644
--- a/routers/web/user/setting/account_test.go
+++ b/routers/web/user/setting/account_test.go
@@ -83,7 +83,7 @@ func TestChangePassword(t *testing.T) {
 		t.Run(req.OldPassword+"__"+req.NewPassword, func(t *testing.T) {
 			unittest.PrepareTestEnv(t)
 			setting.PasswordComplexity = req.PasswordComplexity
-			ctx := test.MockContext(t, "user/settings/security")
+			ctx, _ := test.MockContext(t, "user/settings/security")
 			test.LoadUser(t, ctx, 2)
 			test.LoadRepo(t, ctx, 1)
 
diff --git a/routers/web/web.go b/routers/web/web.go
index 8683ef221d..fae935a507 100644
--- a/routers/web/web.go
+++ b/routers/web/web.go
@@ -104,7 +104,7 @@ func ctxDataSet(args ...any) func(ctx *context.Context) {
 }
 
 // Routes returns all web routes
-func Routes(ctx gocontext.Context) *web.Route {
+func Routes() *web.Route {
 	routes := web.NewRoute()
 
 	routes.Head("/", misc.DummyOK) // for health check - doesn't need to be passed through gzip handler
@@ -146,13 +146,8 @@ func Routes(ctx gocontext.Context) *web.Route {
 
 	mid = append(mid, common.Sessioner(), context.Contexter())
 
-	group := buildAuthGroup()
-	if err := group.Init(ctx); err != nil {
-		log.Error("Could not initialize '%s' auth method, error: %s", group.Name(), err)
-	}
-
 	// Get user from session if logged in.
-	mid = append(mid, auth_service.Auth(group))
+	mid = append(mid, auth_service.Auth(buildAuthGroup()))
 
 	// GetHead allows a HEAD request redirect to GET if HEAD method is not defined for that route
 	mid = append(mid, middleware.GetHead)
diff --git a/services/auth/group.go b/services/auth/group.go
index 0a0330b3aa..a1ff65f203 100644
--- a/services/auth/group.go
+++ b/services/auth/group.go
@@ -4,7 +4,6 @@
 package auth
 
 import (
-	"context"
 	"net/http"
 	"reflect"
 	"strings"
@@ -14,9 +13,7 @@ import (
 
 // Ensure the struct implements the interface.
 var (
-	_ Method        = &Group{}
-	_ Initializable = &Group{}
-	_ Freeable      = &Group{}
+	_ Method = &Group{}
 )
 
 // Group implements the Auth interface with serval Auth.
@@ -49,35 +46,6 @@ func (b *Group) Name() string {
 	return strings.Join(names, ",")
 }
 
-// Init does nothing as the Basic implementation does not need to allocate any resources
-func (b *Group) Init(ctx context.Context) error {
-	for _, method := range b.methods {
-		initializable, ok := method.(Initializable)
-		if !ok {
-			continue
-		}
-
-		if err := initializable.Init(ctx); err != nil {
-			return err
-		}
-	}
-	return nil
-}
-
-// Free does nothing as the Basic implementation does not have to release any resources
-func (b *Group) Free() error {
-	for _, method := range b.methods {
-		freeable, ok := method.(Freeable)
-		if !ok {
-			continue
-		}
-		if err := freeable.Free(); err != nil {
-			return err
-		}
-	}
-	return nil
-}
-
 // Verify extracts and validates
 func (b *Group) Verify(req *http.Request, w http.ResponseWriter, store DataStore, sess SessionStore) (*user_model.User, error) {
 	// Try to sign in with each of the enabled plugins
diff --git a/services/auth/interface.go b/services/auth/interface.go
index c4a8a20d01..508291fa43 100644
--- a/services/auth/interface.go
+++ b/services/auth/interface.go
@@ -29,26 +29,11 @@ type Method interface {
 	Verify(http *http.Request, w http.ResponseWriter, store DataStore, sess SessionStore) (*user_model.User, error)
 }
 
-// Initializable represents a structure that requires initialization
-// It usually should only be called once before anything else is called
-type Initializable interface {
-	// Init should be called exactly once before using any of the other methods,
-	// in order to allow the plugin to allocate necessary resources
-	Init(ctx context.Context) error
-}
-
 // Named represents a named thing
 type Named interface {
 	Name() string
 }
 
-// Freeable represents a structure that is required to be freed
-type Freeable interface {
-	// Free should be called exactly once before application closes, in order to
-	// give chance to the plugin to free any allocated resources
-	Free() error
-}
-
 // PasswordAuthenticator represents a source of authentication
 type PasswordAuthenticator interface {
 	Authenticate(user *user_model.User, login, password string) (*user_model.User, error)
diff --git a/services/auth/sspi_windows.go b/services/auth/sspi_windows.go
index d49497e19c..c162810797 100644
--- a/services/auth/sspi_windows.go
+++ b/services/auth/sspi_windows.go
@@ -4,10 +4,10 @@
 package auth
 
 import (
-	"context"
 	"errors"
 	"net/http"
 	"strings"
+	"sync"
 
 	"code.gitea.io/gitea/models/auth"
 	"code.gitea.io/gitea/models/avatars"
@@ -32,13 +32,12 @@ var (
 	// sspiAuth is a global instance of the websspi authentication package,
 	// which is used to avoid acquiring the server credential handle on
 	// every request
-	sspiAuth *websspi.Authenticator
+	sspiAuth     *websspi.Authenticator
+	sspiAuthOnce sync.Once
 
 	// Ensure the struct implements the interface.
-	_ Method        = &SSPI{}
-	_ Named         = &SSPI{}
-	_ Initializable = &SSPI{}
-	_ Freeable      = &SSPI{}
+	_ Method = &SSPI{}
+	_ Named  = &SSPI{}
 )
 
 // SSPI implements the SingleSignOn interface and authenticates requests
@@ -47,32 +46,25 @@ var (
 // Returns nil if authentication fails.
 type SSPI struct{}
 
-// Init creates a new global websspi.Authenticator object
-func (s *SSPI) Init(ctx context.Context) error {
-	config := websspi.NewConfig()
-	var err error
-	sspiAuth, err = websspi.New(config)
-	if err != nil {
-		return err
-	}
-	return nil
-}
-
 // Name represents the name of auth method
 func (s *SSPI) Name() string {
 	return "sspi"
 }
 
-// Free releases resources used by the global websspi.Authenticator object
-func (s *SSPI) Free() error {
-	return sspiAuth.Free()
-}
-
 // Verify uses SSPI (Windows implementation of SPNEGO) to authenticate the request.
 // If authentication is successful, returns the corresponding user object.
 // If negotiation should continue or authentication fails, immediately returns a 401 HTTP
 // response code, as required by the SPNEGO protocol.
 func (s *SSPI) Verify(req *http.Request, w http.ResponseWriter, store DataStore, sess SessionStore) (*user_model.User, error) {
+	var errInit error
+	sspiAuthOnce.Do(func() {
+		config := websspi.NewConfig()
+		sspiAuth, errInit = websspi.New(config)
+	})
+	if errInit != nil {
+		return nil, errInit
+	}
+
 	if !s.shouldAuthenticate(req) {
 		return nil, nil
 	}
diff --git a/services/repository/archiver/archiver_test.go b/services/repository/archiver/archiver_test.go
index 3cd6e81351..4b6fb7446d 100644
--- a/services/repository/archiver/archiver_test.go
+++ b/services/repository/archiver/archiver_test.go
@@ -24,7 +24,7 @@ func TestMain(m *testing.M) {
 func TestArchive_Basic(t *testing.T) {
 	assert.NoError(t, unittest.PrepareTestDatabase())
 
-	ctx := test.MockContext(t, "user27/repo49")
+	ctx, _ := test.MockContext(t, "user27/repo49")
 	firstCommit, secondCommit := "51f84af23134", "aacbdfe9e1c4"
 
 	test.LoadRepo(t, ctx, 49)
diff --git a/services/repository/files/content_test.go b/services/repository/files/content_test.go
index a43b71cf31..8ff96822c9 100644
--- a/services/repository/files/content_test.go
+++ b/services/repository/files/content_test.go
@@ -54,7 +54,7 @@ func getExpectedReadmeContentsResponse() *api.ContentsResponse {
 
 func TestGetContents(t *testing.T) {
 	unittest.PrepareTestEnv(t)
-	ctx := test.MockContext(t, "user2/repo1")
+	ctx, _ := test.MockContext(t, "user2/repo1")
 	ctx.SetParams(":id", "1")
 	test.LoadRepo(t, ctx, 1)
 	test.LoadRepoCommit(t, ctx)
@@ -82,7 +82,7 @@ func TestGetContents(t *testing.T) {
 
 func TestGetContentsOrListForDir(t *testing.T) {
 	unittest.PrepareTestEnv(t)
-	ctx := test.MockContext(t, "user2/repo1")
+	ctx, _ := test.MockContext(t, "user2/repo1")
 	ctx.SetParams(":id", "1")
 	test.LoadRepo(t, ctx, 1)
 	test.LoadRepoCommit(t, ctx)
@@ -117,7 +117,7 @@ func TestGetContentsOrListForDir(t *testing.T) {
 
 func TestGetContentsOrListForFile(t *testing.T) {
 	unittest.PrepareTestEnv(t)
-	ctx := test.MockContext(t, "user2/repo1")
+	ctx, _ := test.MockContext(t, "user2/repo1")
 	ctx.SetParams(":id", "1")
 	test.LoadRepo(t, ctx, 1)
 	test.LoadRepoCommit(t, ctx)
@@ -145,7 +145,7 @@ func TestGetContentsOrListForFile(t *testing.T) {
 
 func TestGetContentsErrors(t *testing.T) {
 	unittest.PrepareTestEnv(t)
-	ctx := test.MockContext(t, "user2/repo1")
+	ctx, _ := test.MockContext(t, "user2/repo1")
 	ctx.SetParams(":id", "1")
 	test.LoadRepo(t, ctx, 1)
 	test.LoadRepoCommit(t, ctx)
@@ -176,7 +176,7 @@ func TestGetContentsErrors(t *testing.T) {
 
 func TestGetContentsOrListErrors(t *testing.T) {
 	unittest.PrepareTestEnv(t)
-	ctx := test.MockContext(t, "user2/repo1")
+	ctx, _ := test.MockContext(t, "user2/repo1")
 	ctx.SetParams(":id", "1")
 	test.LoadRepo(t, ctx, 1)
 	test.LoadRepoCommit(t, ctx)
@@ -207,7 +207,7 @@ func TestGetContentsOrListErrors(t *testing.T) {
 
 func TestGetContentsOrListOfEmptyRepos(t *testing.T) {
 	unittest.PrepareTestEnv(t)
-	ctx := test.MockContext(t, "user30/empty")
+	ctx, _ := test.MockContext(t, "user30/empty")
 	ctx.SetParams(":id", "52")
 	test.LoadRepo(t, ctx, 52)
 	test.LoadUser(t, ctx, 30)
@@ -225,7 +225,7 @@ func TestGetContentsOrListOfEmptyRepos(t *testing.T) {
 
 func TestGetBlobBySHA(t *testing.T) {
 	unittest.PrepareTestEnv(t)
-	ctx := test.MockContext(t, "user2/repo1")
+	ctx, _ := test.MockContext(t, "user2/repo1")
 	test.LoadRepo(t, ctx, 1)
 	test.LoadRepoCommit(t, ctx)
 	test.LoadUser(t, ctx, 2)
diff --git a/services/repository/files/diff_test.go b/services/repository/files/diff_test.go
index 621816e97d..0346e0e9e9 100644
--- a/services/repository/files/diff_test.go
+++ b/services/repository/files/diff_test.go
@@ -17,7 +17,7 @@ import (
 
 func TestGetDiffPreview(t *testing.T) {
 	unittest.PrepareTestEnv(t)
-	ctx := test.MockContext(t, "user2/repo1")
+	ctx, _ := test.MockContext(t, "user2/repo1")
 	ctx.SetParams(":id", "1")
 	test.LoadRepo(t, ctx, 1)
 	test.LoadRepoCommit(t, ctx)
@@ -139,7 +139,7 @@ func TestGetDiffPreview(t *testing.T) {
 
 func TestGetDiffPreviewErrors(t *testing.T) {
 	unittest.PrepareTestEnv(t)
-	ctx := test.MockContext(t, "user2/repo1")
+	ctx, _ := test.MockContext(t, "user2/repo1")
 	ctx.SetParams(":id", "1")
 	test.LoadRepo(t, ctx, 1)
 	test.LoadRepoCommit(t, ctx)
diff --git a/services/repository/files/file_test.go b/services/repository/files/file_test.go
index e1c7d5d7fb..d14a049438 100644
--- a/services/repository/files/file_test.go
+++ b/services/repository/files/file_test.go
@@ -98,7 +98,7 @@ func getExpectedFileResponse() *api.FileResponse {
 
 func TestGetFileResponseFromCommit(t *testing.T) {
 	unittest.PrepareTestEnv(t)
-	ctx := test.MockContext(t, "user2/repo1")
+	ctx, _ := test.MockContext(t, "user2/repo1")
 	ctx.SetParams(":id", "1")
 	test.LoadRepo(t, ctx, 1)
 	test.LoadRepoCommit(t, ctx)
diff --git a/services/repository/files/tree_test.go b/services/repository/files/tree_test.go
index a500dbdb22..51a2190e8f 100644
--- a/services/repository/files/tree_test.go
+++ b/services/repository/files/tree_test.go
@@ -15,7 +15,7 @@ import (
 
 func TestGetTreeBySHA(t *testing.T) {
 	unittest.PrepareTestEnv(t)
-	ctx := test.MockContext(t, "user2/repo1")
+	ctx, _ := test.MockContext(t, "user2/repo1")
 	test.LoadRepo(t, ctx, 1)
 	test.LoadRepoCommit(t, ctx)
 	test.LoadUser(t, ctx, 2)
diff --git a/tests/e2e/e2e_test.go b/tests/e2e/e2e_test.go
index fbcb0e7da5..c4b0b62199 100644
--- a/tests/e2e/e2e_test.go
+++ b/tests/e2e/e2e_test.go
@@ -38,7 +38,7 @@ func TestMain(m *testing.M) {
 	defer cancel()
 
 	tests.InitTest(false)
-	c = routers.NormalRoutes(context.TODO())
+	c = routers.NormalRoutes()
 
 	os.Unsetenv("GIT_AUTHOR_NAME")
 	os.Unsetenv("GIT_AUTHOR_EMAIL")
diff --git a/tests/integration/api_activitypub_person_test.go b/tests/integration/api_activitypub_person_test.go
index 301cfba172..a1ce802709 100644
--- a/tests/integration/api_activitypub_person_test.go
+++ b/tests/integration/api_activitypub_person_test.go
@@ -22,10 +22,10 @@ import (
 
 func TestActivityPubPerson(t *testing.T) {
 	setting.Federation.Enabled = true
-	c = routers.NormalRoutes(context.TODO())
+	c = routers.NormalRoutes()
 	defer func() {
 		setting.Federation.Enabled = false
-		c = routers.NormalRoutes(context.TODO())
+		c = routers.NormalRoutes()
 	}()
 
 	onGiteaRun(t, func(*testing.T, *url.URL) {
@@ -60,10 +60,10 @@ func TestActivityPubPerson(t *testing.T) {
 
 func TestActivityPubMissingPerson(t *testing.T) {
 	setting.Federation.Enabled = true
-	c = routers.NormalRoutes(context.TODO())
+	c = routers.NormalRoutes()
 	defer func() {
 		setting.Federation.Enabled = false
-		c = routers.NormalRoutes(context.TODO())
+		c = routers.NormalRoutes()
 	}()
 
 	onGiteaRun(t, func(*testing.T, *url.URL) {
@@ -75,10 +75,10 @@ func TestActivityPubMissingPerson(t *testing.T) {
 
 func TestActivityPubPersonInbox(t *testing.T) {
 	setting.Federation.Enabled = true
-	c = routers.NormalRoutes(context.TODO())
+	c = routers.NormalRoutes()
 	defer func() {
 		setting.Federation.Enabled = false
-		c = routers.NormalRoutes(context.TODO())
+		c = routers.NormalRoutes()
 	}()
 
 	srv := httptest.NewServer(c)
diff --git a/tests/integration/api_nodeinfo_test.go b/tests/integration/api_nodeinfo_test.go
index bc2f11a7f2..158a866091 100644
--- a/tests/integration/api_nodeinfo_test.go
+++ b/tests/integration/api_nodeinfo_test.go
@@ -4,7 +4,6 @@
 package integration
 
 import (
-	"context"
 	"net/http"
 	"net/url"
 	"testing"
@@ -18,10 +17,10 @@ import (
 
 func TestNodeinfo(t *testing.T) {
 	setting.Federation.Enabled = true
-	c = routers.NormalRoutes(context.TODO())
+	c = routers.NormalRoutes()
 	defer func() {
 		setting.Federation.Enabled = false
-		c = routers.NormalRoutes(context.TODO())
+		c = routers.NormalRoutes()
 	}()
 
 	onGiteaRun(t, func(*testing.T, *url.URL) {
diff --git a/tests/integration/create_no_session_test.go b/tests/integration/create_no_session_test.go
index 9a96ed61fa..535d0d4955 100644
--- a/tests/integration/create_no_session_test.go
+++ b/tests/integration/create_no_session_test.go
@@ -4,7 +4,6 @@
 package integration
 
 import (
-	"context"
 	"net/http"
 	"net/http/httptest"
 	"os"
@@ -57,7 +56,7 @@ func TestSessionFileCreation(t *testing.T) {
 	oldSessionConfig := setting.SessionConfig.ProviderConfig
 	defer func() {
 		setting.SessionConfig.ProviderConfig = oldSessionConfig
-		c = routers.NormalRoutes(context.TODO())
+		c = routers.NormalRoutes()
 	}()
 
 	var config session.Options
@@ -76,7 +75,7 @@ func TestSessionFileCreation(t *testing.T) {
 
 	setting.SessionConfig.ProviderConfig = string(newConfigBytes)
 
-	c = routers.NormalRoutes(context.TODO())
+	c = routers.NormalRoutes()
 
 	t.Run("NoSessionOnViewIssue", func(t *testing.T) {
 		defer tests.PrintCurrentTest(t)()
diff --git a/tests/integration/integration_test.go b/tests/integration/integration_test.go
index 27918a9ccc..2318ab9bb9 100644
--- a/tests/integration/integration_test.go
+++ b/tests/integration/integration_test.go
@@ -87,7 +87,7 @@ func TestMain(m *testing.M) {
 	defer cancel()
 
 	tests.InitTest(true)
-	c = routers.NormalRoutes(context.TODO())
+	c = routers.NormalRoutes()
 
 	// integration test settings...
 	if setting.CfgProvider != nil {
diff --git a/tests/integration/repofiles_change_test.go b/tests/integration/repofiles_change_test.go
index a257b95a84..c273d38188 100644
--- a/tests/integration/repofiles_change_test.go
+++ b/tests/integration/repofiles_change_test.go
@@ -244,7 +244,7 @@ func getExpectedFileResponseForRepofilesUpdate(commitID, filename, lastCommitSHA
 func TestChangeRepoFilesForCreate(t *testing.T) {
 	// setup
 	onGiteaRun(t, func(t *testing.T, u *url.URL) {
-		ctx := test.MockContext(t, "user2/repo1")
+		ctx, _ := test.MockContext(t, "user2/repo1")
 		ctx.SetParams(":id", "1")
 		test.LoadRepo(t, ctx, 1)
 		test.LoadRepoCommit(t, ctx)
@@ -281,7 +281,7 @@ func TestChangeRepoFilesForCreate(t *testing.T) {
 func TestChangeRepoFilesForUpdate(t *testing.T) {
 	// setup
 	onGiteaRun(t, func(t *testing.T, u *url.URL) {
-		ctx := test.MockContext(t, "user2/repo1")
+		ctx, _ := test.MockContext(t, "user2/repo1")
 		ctx.SetParams(":id", "1")
 		test.LoadRepo(t, ctx, 1)
 		test.LoadRepoCommit(t, ctx)
@@ -315,7 +315,7 @@ func TestChangeRepoFilesForUpdate(t *testing.T) {
 func TestChangeRepoFilesForUpdateWithFileMove(t *testing.T) {
 	// setup
 	onGiteaRun(t, func(t *testing.T, u *url.URL) {
-		ctx := test.MockContext(t, "user2/repo1")
+		ctx, _ := test.MockContext(t, "user2/repo1")
 		ctx.SetParams(":id", "1")
 		test.LoadRepo(t, ctx, 1)
 		test.LoadRepoCommit(t, ctx)
@@ -366,7 +366,7 @@ func TestChangeRepoFilesForUpdateWithFileMove(t *testing.T) {
 func TestChangeRepoFilesWithoutBranchNames(t *testing.T) {
 	// setup
 	onGiteaRun(t, func(t *testing.T, u *url.URL) {
-		ctx := test.MockContext(t, "user2/repo1")
+		ctx, _ := test.MockContext(t, "user2/repo1")
 		ctx.SetParams(":id", "1")
 		test.LoadRepo(t, ctx, 1)
 		test.LoadRepoCommit(t, ctx)
@@ -402,7 +402,7 @@ func TestChangeRepoFilesForDelete(t *testing.T) {
 func testDeleteRepoFiles(t *testing.T, u *url.URL) {
 	// setup
 	unittest.PrepareTestEnv(t)
-	ctx := test.MockContext(t, "user2/repo1")
+	ctx, _ := test.MockContext(t, "user2/repo1")
 	ctx.SetParams(":id", "1")
 	test.LoadRepo(t, ctx, 1)
 	test.LoadRepoCommit(t, ctx)
@@ -441,7 +441,7 @@ func TestChangeRepoFilesForDeleteWithoutBranchNames(t *testing.T) {
 func testDeleteRepoFilesWithoutBranchNames(t *testing.T, u *url.URL) {
 	// setup
 	unittest.PrepareTestEnv(t)
-	ctx := test.MockContext(t, "user2/repo1")
+	ctx, _ := test.MockContext(t, "user2/repo1")
 	ctx.SetParams(":id", "1")
 	test.LoadRepo(t, ctx, 1)
 	test.LoadRepoCommit(t, ctx)
@@ -471,7 +471,7 @@ func testDeleteRepoFilesWithoutBranchNames(t *testing.T, u *url.URL) {
 func TestChangeRepoFilesErrors(t *testing.T) {
 	// setup
 	onGiteaRun(t, func(t *testing.T, u *url.URL) {
-		ctx := test.MockContext(t, "user2/repo1")
+		ctx, _ := test.MockContext(t, "user2/repo1")
 		ctx.SetParams(":id", "1")
 		test.LoadRepo(t, ctx, 1)
 		test.LoadRepoCommit(t, ctx)