Skip to content

Commit 57422cf

Browse files
committedNov 18, 2020
Added db configuration and db testing
1 parent 40d23ff commit 57422cf

12 files changed

+210
-1
lines changed
 

‎configs/apiserver.toml

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
bind_addr = ":8080"
2-
log_level = "debug"
2+
log_level = "debug"
3+
4+
[store]
5+
database_url = "postgres://postgres:211217ns@localhost/restapi_dev?sslmode=disable"

‎go.mod

+2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ go 1.15
44

55
require (
66
github.com/BurntSushi/toml v0.3.1
7+
github.com/golang-migrate/migrate v3.5.4+incompatible // indirect
78
github.com/gorilla/mux v1.8.0
9+
github.com/lib/pq v1.8.0
810
github.com/sirupsen/logrus v1.7.0
911
github.com/stretchr/testify v1.6.1
1012
)

‎go.sum

+5
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,13 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
33
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
44
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
55
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
6+
github.com/golang-migrate/migrate v1.3.2 h1:QAlFV1QF9zdkzy/jujlBVkVu+L/+k18cg8tuY1/4JDY=
7+
github.com/golang-migrate/migrate v3.5.4+incompatible h1:R7OzwvCJTCgwapPCiX6DyBiu2czIUMDCB118gFTKTUA=
8+
github.com/golang-migrate/migrate v3.5.4+incompatible/go.mod h1:IsVUlFN5puWOmXrqjgGUfIRIbU7mr8oNBE2tyERd9Wk=
69
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
710
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
11+
github.com/lib/pq v1.8.0 h1:9xohqzkUwzR4Ga4ivdTcawVS89YSDVxXMa3xJX3cGzg=
12+
github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
813
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
914
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
1015
github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=

‎interanal/app/model/user.go

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package model
2+
3+
//User ...
4+
type User struct {
5+
ID int
6+
Email string
7+
EncryptedPassword string
8+
}
9+

‎interanal/app/store/config.go

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package store
2+
3+
//Config ...
4+
type Config struct {
5+
DatabaseURL string `toml:"database_url"`
6+
}
7+
8+
//NewConfig ...
9+
func NewConfig() *Config {
10+
return &Config{}
11+
}

‎interanal/app/store/store.go

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package store
2+
3+
import (
4+
"database/sql"
5+
6+
_ "github.com/lib/pq" // ...
7+
)
8+
9+
//Store ...
10+
type Store struct {
11+
config *Config
12+
db *sql.DB
13+
userRepository *UserRepository
14+
}
15+
16+
//New ...
17+
func New(config *Config) *Store {
18+
return &Store{
19+
config: config,
20+
}
21+
}
22+
23+
//Open ...
24+
func (s *Store) Open() error {
25+
db, err := sql.Open("postgres", s.config.DatabaseURL)
26+
if err != nil {
27+
return err
28+
}
29+
30+
if err := db.Ping(); err != nil {
31+
return err
32+
}
33+
34+
s.db = db
35+
36+
return nil
37+
}
38+
39+
//Close ...
40+
func (s *Store) Close() {
41+
s.db.Close()
42+
}
43+
44+
//User ...
45+
func (s *Store) User() *UserRepository {
46+
if s.userRepository != nil {
47+
return s.userRepository
48+
}
49+
50+
s.userRepository = &UserRepository{
51+
store: s,
52+
}
53+
54+
return s.userRepository
55+
}

‎interanal/app/store/store_test.go

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package store_test
2+
3+
import (
4+
"os"
5+
"testing"
6+
)
7+
8+
var (
9+
databaseURL string
10+
)
11+
12+
func TestMain(m *testing.M) {
13+
databaseURL = os.Getenv("database_url")
14+
if databaseURL == "" {
15+
databaseURL = "postgres://postgres:211217ns@localhost/restapi_test?sslmode=disable"
16+
}
17+
18+
os.Exit(m.Run())
19+
}

‎interanal/app/store/testing.go

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package store
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
"testing"
7+
)
8+
9+
//TestStore ...
10+
func TestStore(t *testing.T, databaseURL string) (*Store, func(...string)) {
11+
t.Helper()
12+
config := NewConfig()
13+
config.DatabaseURL = databaseURL
14+
s := New(config)
15+
if err := s.Open(); err != nil {
16+
t.Fatal(err)
17+
}
18+
19+
return s, func(tables ...string) {
20+
if len(tables) > 0 {
21+
if _, err := s.db.Exec(fmt.Sprintf("truncate %s cascade", strings.Join(tables, ", "))); err != nil {
22+
t.Fatal(err)
23+
}
24+
}
25+
s.Close()
26+
}
27+
}

‎interanal/app/store/userrepository.go

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package store
2+
3+
import "github.com/dannycrief/go-http-rest-api/interanal/app/model"
4+
5+
//UserRepository ...
6+
type UserRepository struct {
7+
store *Store
8+
}
9+
10+
//Create ...
11+
func (r *UserRepository) Create(u *model.User) (*model.User, error) {
12+
if err := r.store.db.QueryRow(
13+
"insert into users (email, encrypted_password) values ($1, $2) returning id",
14+
u.Email, u.EncryptedPassword,
15+
).Scan(&u.ID); err != nil {
16+
return nil, err
17+
}
18+
19+
return u, nil
20+
}
21+
22+
//FindByEmail ...
23+
func (r *UserRepository) FindByEmail(email string) (*model.User, error) {
24+
u := &model.User{}
25+
if err := r.store.db.QueryRow(
26+
"select id, email, encrypted_password from users where email = $1",
27+
email,
28+
).Scan(
29+
&u.ID,
30+
&u.Email,
31+
&u.EncryptedPassword,
32+
); err != nil {
33+
return nil, err
34+
}
35+
return u, nil
36+
}
+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package store_test
2+
3+
import (
4+
"github.com/dannycrief/go-http-rest-api/interanal/app/model"
5+
"github.com/dannycrief/go-http-rest-api/interanal/app/store"
6+
"github.com/stretchr/testify/assert"
7+
"testing"
8+
)
9+
10+
func TestUserRepository_Create(t *testing.T) {
11+
s, teardown := store.TestStore(t, databaseURL)
12+
defer teardown("users")
13+
14+
u, err := s.User().Create(&model.User{
15+
Email: "user@example.org",
16+
})
17+
assert.NoError(t, err)
18+
assert.NotNil(t, u)
19+
}
20+
21+
func TestUserRepository_FindByEmail(t *testing.T) {
22+
s, teardown := store.TestStore(t, databaseURL)
23+
defer teardown("users")
24+
25+
email := "user@example.org"
26+
_, err := s.User().FindByEmail(email)
27+
assert.Error(t, err)
28+
29+
s.User().Create(&model.User{
30+
Email: "user@example.org",
31+
})
32+
u, err := s.User().FindByEmail(email)
33+
assert.NoError(t, err)
34+
assert.NotNil(t, u)
35+
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
drop table users;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
create table users (
2+
id bigserial not null primary key,
3+
email varchar not null unique,
4+
encrypted_password varchar not null
5+
);

0 commit comments

Comments
 (0)
Please sign in to comment.