package auth import ( "database/sql" "errors" "testing" "time" "github.com/DATA-DOG/go-sqlmock" "golang.org/x/crypto/bcrypt" ) func TestAuthenticate(t *testing.T) { db, mock, err := sqlmock.New() if err != nil { t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) } defer db.Close() service := NewService(db) password := "secret" hash, _ := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) rows := sqlmock.NewRows([]string{"id", "username", "password_hash", "created_at"}). AddRow(1, "testuser", string(hash), time.Now()) mock.ExpectQuery("SELECT id, username, password_hash, created_at FROM users WHERE username = ?"). WithArgs("testuser"). WillReturnRows(rows) user, err := service.Authenticate("testuser", password) if err != nil { t.Errorf("expected no error, got %v", err) } if user == nil { t.Errorf("expected user, got nil") } if user.Username != "testuser" { t.Errorf("expected username testuser, got %s", user.Username) } if err := mock.ExpectationsWereMet(); err != nil { t.Errorf("there were unfulfilled expectations: %s", err) } } func TestAuthenticate_InvalidCredentials(t *testing.T) { db, mock, err := sqlmock.New() if err != nil { t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) } defer db.Close() service := NewService(db) mock.ExpectQuery("SELECT id, username, password_hash, created_at FROM users WHERE username = ?"). WithArgs("nonexistent"). WillReturnError(sql.ErrNoRows) _, err = service.Authenticate("nonexistent", "password") if !errors.Is(err, ErrInvalidCredentials) { t.Errorf("expected ErrInvalidCredentials, got %v", err) } if err := mock.ExpectationsWereMet(); err != nil { t.Errorf("there were unfulfilled expectations: %s", err) } } func TestCreateUser(t *testing.T) { db, mock, err := sqlmock.New() if err != nil { t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) } defer db.Close() service := NewService(db) // Expect check if user exists mock.ExpectQuery("SELECT id, username, password_hash, created_at FROM users WHERE username = ?"). WithArgs("newuser"). WillReturnError(sql.ErrNoRows) // Expect insert mock.ExpectExec("INSERT INTO users"). WithArgs("newuser", sqlmock.AnyArg()). WillReturnResult(sqlmock.NewResult(1, 1)) // Expect retrieve created user rows := sqlmock.NewRows([]string{"id", "username", "password_hash", "created_at"}). AddRow(1, "newuser", "hashedpassword", time.Now()) mock.ExpectQuery("SELECT id, username, password_hash, created_at FROM users WHERE id = ?"). WithArgs(1). WillReturnRows(rows) user, err := service.CreateUser("newuser", "password") if err != nil { t.Errorf("expected no error, got %v", err) } if user.Username != "newuser" { t.Errorf("expected username newuser, got %s", user.Username) } if err := mock.ExpectationsWereMet(); err != nil { t.Errorf("there were unfulfilled expectations: %s", err) } }