I am creating a mock database with Golang interfaces to test my handler function. However, I don't seem to be performing the dependency injection correctly in my unit testing environment. I have created a setup_test.go
file to set up my mock database environment. In the code snippets below, I will go over the flow of how my dependency injection works.
main.go
package main
type application struct {
DB repository.DatabaseRepo
}
func main() {
app := application{}
conn, err := app.connectToDB()
if err != nil {
log.Fatal("Failed to connect to PostgreSQL:", err)
}
defer func() {
conn.Close(context.Background())
}()
app.DB = &dbrepo.PostgresDBRepo{DB: conn}
// Passing app.DB to routes function for DI
mux := routes.Routes(app.DB)
package repository
type DatabaseRepo interface {
Connection() *pgx.Conn
GetCountByUsername(ctx context.Context, username string) (int, error)
}
routes.go
package routes
func Routes(app repository.DatabaseRepo) http.Handler {
mux := chi.NewRouter()
signUpH := user.New(app)
mux.Post("/signup", utils.MakeHTTPHandler(signUpH.SignUp))
}
SignUp.go
The code fails at this line which is calling the database. I have set up my mock database in point 4 insetup_test.go
. This is the error message I am getting "panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation ...]".
package user
type application struct {
DB repository.DatabaseRepo
}
// Dependency Injection of Repository (Database)
func New(app repository.DatabaseRepo) *application {
return &application{DB: app}
}
func (app application) SignUp(w http.ResponseWriter, req *http.Request) error {
// some other logic
// When I run `go run .`, this prints out to be *dbrepo.PostgresDBRepo
// When I run `go test -v ./...`, this prints out to be <nil>
// but the expected type should be *dbrepo.TestDBRepo
fmt.Printf("Type of app.DB: %T\n", app.DB)
// fails on this line in unit testing
userCount, err := app.DB.GetCountByUsername(ctx, Username)
// some other logic
}
setup_test.go
package main
var app application
func TestMain(m *testing.M) {
app.DB = &dbrepo.TestDBRepo{}
fmt.Printf("Type of app.DB: %T\n", app.DB) // output type is *dbrepo.TestDBRepo
os.Exit(m.Run())
}
I have seen many unit testing for similar mock database using this approach but they usually do it within the same package main which will not have this issue if you have nested folders and packages like mine.
What can I try next?