-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add PostgreSQL support to stock-persistence module
This commit introduces PostgreSQL support to the stock-persistence module, enables database connection testing and handles connection errors. New Go files added under the infrastructure/database and database/postgres directories implement the database functionality. The module now depends on the lib/pq PostgreSQL driver and the go-sqlmock library for mocking SQL queries during testing.
- Loading branch information
Showing
5 changed files
with
196 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
module github.com/Helgart/stock-persistence | ||
|
||
go 1.22.1 | ||
|
||
require ( | ||
github.com/DATA-DOG/go-sqlmock v1.5.2 | ||
github.com/lib/pq v1.10.9 | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU= | ||
github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU= | ||
github.com/kisielk/sqlstruct v0.0.0-20201105191214-5f3e10d3ab46/go.mod h1:yyMNCyc/Ib3bDTKd379tNMpB/7/H5TjM2Y9QJ5THLbE= | ||
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= | ||
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
package database | ||
|
||
import ( | ||
"database/sql" | ||
"fmt" | ||
) | ||
|
||
// connexionErrorMessage represents the error message format for a database connection error. | ||
const connexionErrorMessage = "Database connexion error (%s@%s:%d/%s) : %s" | ||
|
||
// Database is a type that represents a database connection. | ||
type Database struct { | ||
connexion *sql.DB | ||
} | ||
|
||
// DatabaseParameters represents the parameters used to establish a database connection. | ||
type DatabaseParameters struct { | ||
Host string | ||
Port uint | ||
User string | ||
Password string | ||
Name string | ||
} | ||
|
||
// ConnexionError represents an error that occurred during database connection. | ||
type ConnexionError struct { | ||
PreviousError error | ||
PsqlInfo string | ||
DatabaseParameters DatabaseParameters | ||
} | ||
|
||
// Error returns the error message representation of a ConnexionError. | ||
func (connexionError ConnexionError) Error() string { | ||
return fmt.Sprintf( | ||
connexionErrorMessage, | ||
connexionError.DatabaseParameters.User, | ||
connexionError.DatabaseParameters.Host, | ||
connexionError.DatabaseParameters.Port, | ||
connexionError.DatabaseParameters.Name, | ||
connexionError.PreviousError.Error(), | ||
) | ||
} | ||
|
||
// NewDatabase creates a new Database struct with the provided connection. | ||
// It takes a pointer to sql.DB and returns a Database instance. | ||
func NewDatabase(connexion *sql.DB) Database { | ||
return Database{connexion: connexion} | ||
} | ||
|
||
// Ping pings the database to check its availability. | ||
// It returns an error if the ping fails. | ||
func (database *Database) Ping() error { | ||
err := database.connexion.Ping() | ||
|
||
if err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
package database | ||
|
||
import ( | ||
"database/sql" | ||
"fmt" | ||
"testing" | ||
|
||
sqlmock "github.com/DATA-DOG/go-sqlmock" | ||
) | ||
|
||
func TestDatabase_Ping(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
setup func(mock sqlmock.Sqlmock) | ||
wantErr bool | ||
}{ | ||
{ | ||
name: "Success", | ||
setup: func(mock sqlmock.Sqlmock) { | ||
mock.ExpectPing().WillReturnError(nil) | ||
}, | ||
wantErr: false, | ||
}, | ||
{ | ||
name: "Failure", | ||
setup: func(mock sqlmock.Sqlmock) { | ||
mock.ExpectPing().WillReturnError(sql.ErrConnDone) | ||
}, | ||
wantErr: true, | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
db, mock, err := sqlmock.New(sqlmock.MonitorPingsOption(true)) | ||
|
||
if err != nil { | ||
t.Fatalf("an error '%s' was not expected when opening a stub database connection", err) | ||
} | ||
|
||
tt.setup(mock) | ||
|
||
database := NewDatabase(db) | ||
|
||
if err := database.Ping(); (err != nil) != tt.wantErr { | ||
t.Errorf("Database.Ping() error = %v, wantErr %v", err, tt.wantErr) | ||
} | ||
|
||
if err := mock.ExpectationsWereMet(); err != nil { | ||
t.Errorf("Database.Ping() there were unfulfilled expectations: %s", err) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func TestConnexionError_Error(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
err ConnexionError | ||
want string | ||
}{ | ||
{ | ||
name: "Error Message", | ||
err: ConnexionError{ | ||
PreviousError: fmt.Errorf("previousError"), | ||
PsqlInfo: "psqlInfo", | ||
DatabaseParameters: DatabaseParameters{User: "user", Host: "host", Port: 9999, Name: "name"}, | ||
}, | ||
want: fmt.Sprintf(connexionErrorMessage, "user", "host", 9999, "name", "previousError"), | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
if got := tt.err.Error(); got != tt.want { | ||
t.Errorf("ConnexionError.Error() = %v, want %v", got, tt.want) | ||
} | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
package postgres | ||
|
||
import ( | ||
"database/sql" | ||
"fmt" | ||
"github.com/Helgart/stock-persistence/infrastructure/database" | ||
|
||
_ "github.com/lib/pq" | ||
) | ||
|
||
const infoFormat = "host=%s port=%d user=%s password=%s dbname=%s sslmode=disable" | ||
const driver = "postgres" | ||
|
||
func NewDatabase(databaseParameters database.DatabaseParameters) (database.Database, error) { | ||
psqlInfo := fmt.Sprintf( | ||
infoFormat, | ||
databaseParameters.Host, | ||
databaseParameters.Port, | ||
databaseParameters.User, | ||
databaseParameters.Password, | ||
databaseParameters.Name, | ||
) | ||
|
||
connexion, err := sql.Open(driver, psqlInfo) | ||
|
||
if err != nil { | ||
return database.Database{}, database.ConnexionError{ | ||
PreviousError: err, | ||
PsqlInfo: psqlInfo, | ||
DatabaseParameters: databaseParameters, | ||
} | ||
} | ||
|
||
if err := connexion.Ping(); err != nil { | ||
return database.Database{}, database.ConnexionError{ | ||
PreviousError: err, | ||
PsqlInfo: psqlInfo, | ||
DatabaseParameters: databaseParameters, | ||
} | ||
} | ||
|
||
return database.NewDatabase(connexion), nil | ||
} |