DATA-DOG / go-sqlmock

Sql mock driver for golang to test database interactions
Other
5.95k stars 404 forks source link

Even though I type mock.ExpectBegin(), I get db transaction begin error #323

Closed ricirt closed 7 months ago

ricirt commented 9 months ago

Question

I'm trying mock my postgres using go-sqlmock but i'm getting this error

{"time":"2023-10-01T18:07:05.495811+03:00","level":"FATAL","prefix":"-","file":"repository.go","line":"15","message":"An error occurred while executing the query call to ExecQuery 'insert into public."Users" ("Id", "Name", "Email") values ($1,$2,$3)' with args [{Name: Ordinal:1 Value:e918b0bc-76f3-4380-a1fb-a14ca5a08fc3} {Name: Ordinal:2 Value:Jon Snow} {Name: Ordinal:3 Value:jon@jon.com}], was not expected, next expectation is: ExpectedBegin => expecting database transaction Begin"}

The method I am trying to test is adding to db users.I googled this error but couldn't something. Why i'm getting this error?

myTest file

var user = &User{
    Id:    userIdUuid,
    Name:  "Jon Snow",
    Email: "jon@jon.com",
}
func TestUserRepository_create_whenEverythingIsOk(t *testing.T) {
    t.Parallel()
    //arrange
    db, mock, err := sqlmock.New()
    if err != nil {
        t.Fatalf("an error '%s' was not expoected when opening a stub database connection", err)
    }
    defer db.Close()
    mock.ExpectBegin()
    mock.ExpectExec(`insert into public."Users" ("Id", "Name", "Email") values ($1,$2,$3)`).WithArgs(user.Id, user.Name, user.Email)
    mock.ExpectCommit()
    repository := NewUserRepository(db)
    if err := repository.Create(*user); err != nil {
        t.Errorf("error was not expected while inserting user: %s", err)
    }

    if err := mock.ExpectationsWereMet(); err != nil {
        t.Errorf("there were unfulfilled expectations: %s", err)
    }
}

my repository func

func (repo *userRepository) Create(user User) (err error) {
    query := `insert into public."Users" ("Id", "Name", "Email") values ($1,$2,$3)`
    _, err := repo.db.Exec(query, user.Id, user.Name, user.Email)
    if err != nil {
        log.Fatalf("An error occurred while executing the query  %v", err)
    }
    return
}

    my db initilization
func NewDb() (*sql.DB, error) {
    var config configs.Config
    if err := viper.Unmarshal(&config); err != nil {
        fmt.Println(err)
        return nil, err
    }
    db, err := sql.Open("postgres", fmt.Sprintf("%s", config.PostgresConnection[0]["connectionstring"]))

    if err != nil {
        panic("failed to connect database")
    }
    if err := db.Ping(); err != nil {
        log.Fatalf("unable to reach database: %v", err)
    }
    return db, nil
}

func Installer(e *echo.Echo) {

    db, err := db_helper.NewDb()
    if err != nil {
        panic(err)
    }
    userRepo := entities.NewUserRepository(db)
    userService := entities.NewUserService(userRepo)
    controller := entities.NewUserHandler(userService)

    e.GET("api/user/:id", controller.GetById)
    e.POST("api/user", controller.Create)
    e.GET("api/user", controller.GetUsers)
}
charafzellou commented 9 months ago

Hello @ricirt ,

You are getting this error because you are never actually calling db.Begin() in the code snippet above.

Your mock database is expecting the following sequence in this exact order :

    mock.ExpectBegin()
    mock.ExpectExec(`insert into public."Users" ("Id", "Name", "Email") values ($1,$2,$3)`).WithArgs(user.Id, user.Name, user.Email)
    mock.ExpectCommit()

So you should call a db.Begin() then db.Exec(...) using that exact same request.

ricirt commented 7 months ago

thank you ! thats done.