replace redis with mysql

This commit is contained in:
rinosukmandityo
2020-03-18 18:18:03 +07:00
parent b73e4839f4
commit 153d6b638e
15 changed files with 437 additions and 192 deletions

View File

@@ -4,17 +4,28 @@ Sample of hexagonal architecture to handle login logic and user CRUD
How to run
---
#### Set Environment Variable
This application support 2 kind of database Redis and MongoDB to prove our ports is completely agnostic from the implementation.
This application support 2 kind of database MySQL and MongoDB to prove our ports is completely agnostic from the implementation.
By default it will connect into our mongo DB database with default host & port `localhost:27017` and collection `local`
To connect into different database we need to set database information in environment variable
To connect into different database we need to set database information in environment variable
```go
1. MongoDB
```cli
set mongo_url=mongodb://localhost:27017/local
set mongo_timeout=30
set mongo_db=local
set url_db=mongo
```
2. MySQL
```cli
set mysql_url=root:Password.1@tcp(127.0.0.1:3306)/tes
set mysql_timeout=10
set mysql_db=tes
set url_db=mysql
```
After setting the database information we only need to run the main.go file
`go run main.go`
@@ -91,8 +102,8 @@ We also can make sure that our _**Domain Logic**_ are testable without any of th
#### The service that we are going to build
So we have our service which is a user management and login and it will connect to serializer which will either serialize the data into json or message pack before serving it through REST API
And then on the other side we have our repository which will either choose to use MongoDB or Redis based on how we start the application from command line.
So basically our API will be able to accept JSON or message pack format and also our repository is able to use both MongoDB and Redis and it won't really affect our service
And then on the other side we have our repository which will either choose to use MongoDB or MySQL based on how we start the application from command line.
So basically our API will be able to accept JSON or message pack format and also our repository is able to use both MongoDB and MySQL and it won't really affect our service
Project Structure
---
@@ -106,8 +117,8 @@ contains data models
contains **Port** interface for repository adapter
- **mongodb**
contains mongo **Adapter** that implement UserRepository interface. This package will store mongo client and connect to mongoDB database to handle database query or command
- **redis**
contains redis **Adapter** that implement UserRepository interface. This package will store redis client and connect to redis server to handle database query or data manipulation
- **mysql**
contains MySQL **Adapter** that implement UserRepository interface. This package will store MySQL client and connect to MySQL server to handle database query or data manipulation
4. **serializer**
contains **Port** interface for decode and encode serializer. It will be used in our API to decode and encode data.
- **json**

View File

@@ -30,10 +30,20 @@ import (
===================================
TO SET DATABASE INFO FROM TERMINAL
===================================
=======
MongoDB
=======
set mongo_url=mongodb://localhost:27017/local
set mongo_timeout=10
set mongo_db=local
set url_db=mongo
=======
MySQL
=======
set mysql_url=root:Password.1@tcp(127.0.0.1:3306)/tes
set mysql_timeout=10
set mysql_db=tes
set url_db=mysql
*/
var (

View File

@@ -32,10 +32,20 @@ import (
===================================
TO SET DATABASE INFO FROM TERMINAL
===================================
=======
MongoDB
=======
set mongo_url=mongodb://localhost:27017/local
set mongo_timeout=10
set mongo_db=local
set url_db=mongo
=======
MySQL
=======
set mysql_url=root:Password.1@tcp(127.0.0.1:3306)/tes
set mysql_timeout=10
set mysql_db=tes
set url_db=mysql
*/
var (

View File

@@ -30,7 +30,7 @@ func (u *userService) GetAll() ([]m.User, error) {
}
func (u *userService) GetById(id string) (*m.User, error) {
res, e := u.userRepo.GetBy(map[string]interface{}{"_id": id})
res, e := u.userRepo.GetBy(map[string]interface{}{"ID": id})
if e != nil {
return res, e
}
@@ -62,14 +62,14 @@ func (u *userService) Update(user *m.User) error {
if user.Password != "" {
user.Password = repo.EncryptPassword(user.Password)
}
return u.userRepo.Update(user, map[string]interface{}{"_id": user.ID})
return u.userRepo.Update(user)
}
func (u *userService) Delete(user *m.User) error {
if user.ID == "" {
return errs.Wrap(helper.ErrUserNotFound, "service.User.Delete")
}
if e := u.userRepo.Delete(map[string]interface{}{"_id": user.ID}); e != nil {
if e := u.userRepo.Delete(user); e != nil {
return e
}
return nil

View File

@@ -1,17 +1,13 @@
package models
import (
"strconv"
)
type User struct {
ID string `json:"ID" bson:"_id" msgpack:"_id"`
Username string `json:"Username" bson:"Username" msgpack:"Username"`
Email string `json:"Email" bson:"Email" msgpack:"Email"`
Password string `json:"Password" bson:"Password" msgpack:"Password"`
Name string `json:"Name" bson:"Name" msgpack:"Name"`
Address string `json:"Address" bson:"Address" msgpack:"Address"`
IsActive bool `json:"IsActive" bson:"IsActive" msgpack:"IsActive"`
ID string `json:"ID" bson:"_id" msgpack:"_id" db:"ID"`
Name string `json:"Name" bson:"Name" msgpack:"Name" db:"Name"`
Username string `json:"Username" bson:"Username" msgpack:"Username" db:"Username"`
Email string `json:"Email" bson:"Email" msgpack:"Email" db:"Email"`
Password string `json:"Password" bson:"Password" msgpack:"Password" db:"Password"`
Address string `json:"Address" bson:"Address" msgpack:"Address" db:"Address"`
IsActive bool `json:"IsActive" bson:"IsActive" msgpack:"IsActive" db:"IsActive"`
}
func NewUser() *User {
@@ -33,24 +29,26 @@ func NewUserDefaultData() *User {
return user
}
func (user *User) FormingUserData(data map[string]string) {
user.ID = data["ID"]
user.Username = data["Username"]
user.Email = data["Email"]
user.Password = data["Password"]
user.Name = data["Name"]
user.Address = data["Address"]
user.IsActive, _ = strconv.ParseBool(data["IsActive"])
}
func (user *User) GetMapFormat() map[string]interface{} {
return map[string]interface{}{
"ID": user.ID,
"Name": user.Name,
"Username": user.Username,
"Email": user.Email,
"Password": user.Password,
"Name": user.Name,
"Address": user.Address,
"IsActive": user.IsActive,
}
}
func (user *User) SplitByField() []interface{} {
return []interface{}{
user.ID,
user.Name,
user.Username,
user.Email,
user.Password,
user.Address,
user.IsActive,
}
}

View File

@@ -6,34 +6,46 @@ import (
"strconv"
repo "github.com/rinosukmandityo/hexagonal-login/repositories"
mr "github.com/rinosukmandityo/hexagonal-login/repositories/mongodb"
rr "github.com/rinosukmandityo/hexagonal-login/repositories/redis"
mg "github.com/rinosukmandityo/hexagonal-login/repositories/mongodb"
mr "github.com/rinosukmandityo/hexagonal-login/repositories/mysql"
)
func ChooseRepo() repo.UserRepository {
switch os.Getenv("url_db") {
case "redis":
redisURL := os.Getenv("redis_url")
repo, e := rr.NewUserRedisRepository(redisURL)
case "mysql":
url := os.Getenv("mysql_url")
if url == "" {
url = "root:Password.1@tcp(127.0.0.1:3306)/tes"
}
db := os.Getenv("mysql_db")
if db == "" {
db = "tes"
}
timeout, _ := strconv.Atoi(os.Getenv("mysql_timeout"))
if timeout == 0 {
timeout = 10
}
repo, e := mr.NewUserRepository(url, db, timeout)
if e != nil {
log.Fatal(e)
}
return repo
default:
mongoURL := os.Getenv("mongo_url")
if mongoURL == "" {
mongoURL = "mongodb://localhost:27017/local"
url := os.Getenv("mongo_url")
if url == "" {
url = "mongodb://localhost:27017/local"
}
mongoDB := os.Getenv("mongo_db")
if mongoDB == "" {
mongoDB = "local"
db := os.Getenv("mongo_db")
if db == "" {
db = "local"
}
mongoTimeout, _ := strconv.Atoi(os.Getenv("mongo_timeout"))
if mongoTimeout == 0 {
mongoTimeout = 10
timeout, _ := strconv.Atoi(os.Getenv("mongo_timeout"))
if timeout == 0 {
timeout = 10
}
repo, e := mr.NewUserMongoRepository(mongoURL, mongoDB, mongoTimeout)
repo, e := mg.NewUserMongoRepository(url, db, timeout)
if e != nil {
log.Fatal(e)
}

View File

@@ -66,11 +66,15 @@ func (r *userMongoRepository) GetBy(filter map[string]interface{}) (*m.User, err
ctx, cancel := context.WithTimeout(context.Background(), r.timeout)
defer cancel()
c := r.client.Database(r.database).Collection(res.TableName())
if _, ok := filter["ID"]; ok {
filter["_id"] = filter["ID"]
delete(filter, "ID")
}
if e := c.FindOne(ctx, filter).Decode(res); e != nil {
if e == mongo.ErrNoDocuments {
return res, errors.Wrap(helper.ErrUserNotFound, "repository.User.GetById")
return res, errors.Wrap(helper.ErrUserNotFound, "repository.User.GetBy")
}
return res, errors.Wrap(e, "repository.User.GetById")
return res, errors.Wrap(e, "repository.User.GetBy")
}
return res, nil
@@ -86,10 +90,11 @@ func (r *userMongoRepository) Store(data *m.User) error {
return nil
}
func (r *userMongoRepository) Update(data *m.User, filter map[string]interface{}) error {
func (r *userMongoRepository) Update(data *m.User) error {
ctx, cancel := context.WithTimeout(context.Background(), r.timeout)
defer cancel()
c := r.client.Database(r.database).Collection(data.TableName())
filter := map[string]interface{}{"_id": data.ID}
if res, e := c.UpdateOne(ctx, filter, bson.M{"$set": data}, options.Update().SetUpsert(false)); e != nil {
return errors.Wrap(e, "repository.User.Update")
} else {
@@ -101,9 +106,10 @@ func (r *userMongoRepository) Update(data *m.User, filter map[string]interface{}
return nil
}
func (r *userMongoRepository) Delete(filter map[string]interface{}) error {
func (r *userMongoRepository) Delete(data *m.User) error {
ctx, cancel := context.WithTimeout(context.Background(), r.timeout)
defer cancel()
filter := map[string]interface{}{"_id": data.ID}
c := r.client.Database(r.database).Collection(new(m.User).TableName())
if res, e := c.DeleteOne(ctx, filter); e != nil {
return errors.Wrap(e, "repository.User.Delete")

View File

@@ -0,0 +1,88 @@
package mysql
import (
"fmt"
"strings"
m "github.com/rinosukmandityo/hexagonal-login/models"
)
func constructUpdateQuery(data *m.User, filter map[string]interface{}) (string, []interface{}) {
// "UPDATE <tablename> SET field1=?, field2=? WHERE filter1=?"
dataMap := data.GetMapFormat()
q := fmt.Sprintf("UPDATE %s SET", data.TableName())
values := []interface{}{}
for k, v := range dataMap {
q += fmt.Sprintf(" %s=?,", k)
values = append(values, v)
}
q = strings.TrimSuffix(q, ",")
q += " WHERE"
for k, v := range filter {
q += fmt.Sprintf(" %s=?,", k)
values = append(values, v)
}
q = strings.TrimSuffix(q, ",")
return q, values
}
func constructDeleteQuery(filter map[string]interface{}) (string, []interface{}) {
// "DELETE <tablename> WHERE filter1=?"
q := fmt.Sprintf("DELETE FROM %s WHERE", new(m.User).TableName())
values := []interface{}{}
for k, v := range filter {
q += fmt.Sprintf(" %s=?,", k)
values = append(values, v)
}
q = strings.TrimSuffix(q, ",")
return q, values
}
func constructStoreQuery(data *m.User) (string, []interface{}) {
// "INSERT INTO <tablename> VALUES(?, ?, ?, ?)"
dataFields := data.SplitByField()
q := fmt.Sprintf("INSERT INTO %s VALUES(", data.TableName())
values := []interface{}{}
for _, v := range dataFields {
q += "?,"
values = append(values, v)
}
q = strings.TrimSuffix(q, ",") + ")"
return q, values
}
func constructGetBy(filter map[string]interface{}) (string, []interface{}) {
// SELECT * FROM <tablename> WHERE filter1=filtervalue
q := fmt.Sprintf("SELECT * FROM %s WHERE", new(m.User).TableName())
dataFields := []interface{}{}
for k, v := range filter {
q += fmt.Sprintf(" %s=?,", k)
dataFields = append(dataFields, v)
}
q = strings.TrimSuffix(q, ",")
return q, dataFields
}
func constructGetAll() string {
return "select * from users"
}
func constructAuth(filter map[string]interface{}) (string, []interface{}) {
q := fmt.Sprintf("SELECT * FROM %s WHERE", new(m.User).TableName())
count := 0
dataFields := []interface{}{}
for k, v := range filter {
if count == 0 {
q += fmt.Sprintf(" %s=?", k)
} else {
q += fmt.Sprintf(" OR %s=?", k)
}
dataFields = append(dataFields, v)
count++
}
return q, dataFields
}

View File

@@ -0,0 +1,216 @@
package mysql
import (
"context"
"fmt"
"time"
"github.com/rinosukmandityo/hexagonal-login/helper"
m "github.com/rinosukmandityo/hexagonal-login/models"
repo "github.com/rinosukmandityo/hexagonal-login/repositories"
"database/sql"
_ "github.com/go-sql-driver/mysql"
"github.com/jmoiron/sqlx"
"github.com/pkg/errors"
)
type newsMySQLRepository struct {
url string
timeout time.Duration
}
func newUserClient(URL string) (*sql.DB, error) {
db, e := sql.Open("mysql", URL)
if e != nil {
return nil, e
}
if e = db.Ping(); e != nil {
return nil, e
}
return db, e
}
func (r *newsMySQLRepository) createNewTable() error {
schema := `CREATE TABLE ` + new(m.User).TableName() + ` (
ID VARCHAR(30) NOT NULL UNIQUE,
Name VARCHAR(30),
Username VARCHAR(30) NOT NULL,
Email VARCHAR(50),
Password VARCHAR(50),
Address VARCHAR(50),
IsActive boolean
);`
db, e := sqlx.Connect("mysql", r.url)
if e != nil {
return errors.Wrap(e, "repository.User.CreateTable")
}
defer db.Close()
res, e := db.Exec(schema)
if res != nil && e == nil {
fmt.Println("Table 'Users' created")
}
return nil
}
func NewUserRepository(URL, DB string, timeout int) (repo.UserRepository, error) {
repo := &newsMySQLRepository{
url: fmt.Sprintf("%s?parseTime=true", URL),
timeout: time.Duration(timeout) * time.Second,
}
repo.createNewTable()
return repo, nil
}
func (r *newsMySQLRepository) GetAll() ([]m.User, error) {
res := []m.User{}
db, e := sqlx.Connect("mysql", r.url)
if e != nil {
return res, errors.Wrap(e, "repository.User.GetAll")
}
defer db.Close()
q := constructGetAll()
if e = db.Select(&res, q); e != nil {
return res, errors.Wrap(e, "repository.User.GetAll")
}
return res, nil
}
func (r *newsMySQLRepository) GetBy(filter map[string]interface{}) (*m.User, error) {
res := new(m.User)
db, e := sqlx.Connect("mysql", r.url)
if e != nil {
return res, errors.Wrap(e, "repository.User.GetBy")
}
defer db.Close()
q, dataFields := constructGetBy(filter)
if e = db.Get(res, q, dataFields...); e != nil {
return res, errors.Wrap(e, "repository.User.GetBy")
}
return res, nil
}
func (r *newsMySQLRepository) Store(data *m.User) error {
db, e := newUserClient(r.url)
if e != nil {
return errors.Wrap(e, "repository.User.Store")
}
defer db.Close()
ctx, cancel := context.WithTimeout(context.Background(), r.timeout)
defer cancel()
conn, e := db.Conn(ctx)
if e != nil {
return errors.Wrap(e, "repository.User.Store")
}
q, dataField := constructStoreQuery(data)
stmt, e := conn.PrepareContext(ctx, q)
if e != nil {
return errors.Wrap(e, "repository.User.Store")
}
defer stmt.Close()
if _, e := stmt.Exec(dataField...); e != nil {
return errors.Wrap(e, "repository.User.Store")
}
return nil
}
func (r *newsMySQLRepository) Update(data *m.User) error {
db, e := newUserClient(r.url)
if e != nil {
return errors.Wrap(e, "repository.User.Update")
}
defer db.Close()
ctx, cancel := context.WithTimeout(context.Background(), r.timeout)
defer cancel()
conn, e := db.Conn(ctx)
if e != nil {
return errors.Wrap(e, "repository.User.Update")
}
defer conn.Close()
filter := map[string]interface{}{"ID": data.ID}
q, dataField := constructUpdateQuery(data, filter)
stmt, e := conn.PrepareContext(ctx, q)
if e != nil {
return errors.Wrap(e, "repository.User.Update")
}
defer stmt.Close()
if res, e := stmt.Exec(dataField...); e != nil {
return errors.Wrap(e, "repository.User.Update")
} else {
count, e := res.RowsAffected()
if e != nil {
return errors.Wrap(e, "repository.User.Update")
}
if count == 0 {
return errors.Wrap(helper.ErrUserNotFound, "repository.User.Update")
}
}
return nil
}
func (r *newsMySQLRepository) Delete(data *m.User) error {
db, e := newUserClient(r.url)
if e != nil {
return errors.Wrap(e, "repository.User.Delete")
}
defer db.Close()
ctx, cancel := context.WithTimeout(context.Background(), r.timeout)
defer cancel()
conn, e := db.Conn(ctx)
if e != nil {
return errors.Wrap(e, "repository.User.Delete")
}
defer conn.Close()
filter := map[string]interface{}{"ID": data.ID}
q, dataFields := constructDeleteQuery(filter)
stmt, e := conn.PrepareContext(ctx, q)
if e != nil {
return errors.Wrap(e, "repository.User.Delete")
}
defer stmt.Close()
if res, e := stmt.Exec(dataFields...); e != nil {
return errors.Wrap(e, "repository.User.Delete")
} else {
count, e := res.RowsAffected()
if e != nil {
return errors.Wrap(e, "repository.User.Delete")
}
if count == 0 {
return errors.Wrap(helper.ErrUserNotFound, "repository.User.Delete")
}
}
return nil
}
func (r *newsMySQLRepository) Authenticate(username, password string) (bool, *m.User, error) {
res := new(m.User)
db, e := sqlx.Connect("mysql", r.url)
if e != nil {
return false, res, errors.Wrap(e, "repository.User.Authenticate")
}
defer db.Close()
q, dataFields := constructAuth(map[string]interface{}{"Username": username, "Email": username})
if e = db.Get(res, q, dataFields...); e != nil {
return false, res, errors.Wrap(e, "repository.User.Authenticate")
}
if res.ID == "" {
return false, res, errors.Wrap(helper.ErrUserNotFound, "repository.User.Authenticate")
}
if !repo.IsPasswordMatch(password, res.Password) {
return false, res, errors.New("Password does not match")
}
return true, res, nil
}

View File

@@ -1,9 +0,0 @@
package redis
func FormingData(data map[string]string) map[string]interface{} {
res := map[string]interface{}{}
for k, v := range data {
res[k] = v
}
return res
}

View File

@@ -1,13 +0,0 @@
package redis
import (
"fmt"
)
func generateKey(code string) string {
return fmt.Sprintf("login<>%s", code)
}
func generateUsernameKey(code string) string {
return fmt.Sprintf("login<>username<>%s", code)
}

View File

@@ -1,117 +0,0 @@
package redis
import (
"github.com/rinosukmandityo/hexagonal-login/helper"
m "github.com/rinosukmandityo/hexagonal-login/models"
repo "github.com/rinosukmandityo/hexagonal-login/repositories"
"github.com/go-redis/redis"
"github.com/pkg/errors"
)
type userRedisRepository struct {
client *redis.Client
}
func newUserRedisClient(redisURL string) (*redis.Client, error) {
opt, e := redis.ParseURL(redisURL)
if e != nil {
return nil, e
}
client := redis.NewClient(opt)
if _, e = client.Ping().Result(); e != nil {
return nil, e
}
return client, e
}
func NewUserRedisRepository(redisURL string) (repo.UserRepository, error) {
repo := &userRedisRepository{}
client, e := newUserRedisClient(redisURL)
if e != nil {
return nil, errors.Wrap(e, "repository.NewUserRedisRepository")
}
repo.client = client
return repo, nil
}
func (r *userRedisRepository) GetAll() ([]m.User, error) {
return []m.User{}, nil
}
func (r *userRedisRepository) GetBy(filter map[string]interface{}) (*m.User, error) {
key := generateKey(filter["_id"].(string))
data, e := r.client.HGetAll(key).Result()
user := new(m.User)
if e != nil {
return user, errors.Wrap(e, "repository.User.GetById")
}
if len(data) == 0 {
return user, errors.Wrap(helper.ErrUserNotFound, "repository.User.GetById")
}
user.FormingUserData(data)
return user, nil
}
func (r *userRedisRepository) Store(data *m.User) error {
key := generateKey(data.ID)
redisData := data.GetMapFormat()
if _, e := r.client.HMSet(key, redisData).Result(); e != nil {
return errors.Wrap(e, "repository.User.Store")
}
keyUsername := generateUsernameKey(data.Username)
if _, e := r.client.HMSet(keyUsername, redisData).Result(); e != nil {
return errors.Wrap(e, "repository.User.Store")
}
return nil
}
func (r *userRedisRepository) Update(data *m.User, filter map[string]interface{}) error {
key := generateKey(filter["_id"].(string))
redisData := data.GetMapFormat()
if _, e := r.client.HMSet(key, redisData).Result(); e != nil {
return errors.Wrap(e, "repository.User.Update")
}
keyUsername := generateUsernameKey(filter["username"].(string))
if _, e := r.client.HMSet(keyUsername, redisData).Result(); e != nil {
return errors.Wrap(e, "repository.User.Update")
}
return nil
}
func (r *userRedisRepository) Delete(filter map[string]interface{}) error {
key := generateKey(filter["_id"].(string))
data, e := r.client.HGetAll(key).Result()
if e != nil {
return errors.Wrap(e, "repository.User.Delete")
}
if len(data) == 0 {
return errors.Wrap(errors.New("User Not Found"), "repository.User.Delete")
}
if _, e := r.client.HDel(key).Result(); e != nil {
return errors.Wrap(e, "repository.User.Delete")
}
keyUsername := generateUsernameKey(data["username"])
if _, e := r.client.HDel(keyUsername).Result(); e != nil {
return errors.Wrap(e, "repository.User.Delete")
}
return nil
}
func (r *userRedisRepository) Authenticate(username, password string) (bool, *m.User, error) {
user := new(m.User)
key := generateUsernameKey(username)
data, e := r.client.HGetAll(key).Result()
if e != nil {
return false, user, errors.Wrap(e, "repository.User.Authenticate")
}
if len(data) == 0 {
return false, user, errors.Wrap(errors.New("User Not Found"), "repository.User.Authenticate")
}
if !repo.IsPasswordMatch(password, user.Password) {
return false, user, errors.New("Password does not match")
}
user.FormingUserData(data)
return true, user, nil
}

View File

@@ -8,7 +8,7 @@ type UserRepository interface {
GetAll() ([]m.User, error)
GetBy(filter map[string]interface{}) (*m.User, error)
Store(data *m.User) error
Update(data *m.User, filter map[string]interface{}) error
Delete(filter map[string]interface{}) error
Update(data *m.User) error
Delete(data *m.User) error
Authenticate(username, password string) (bool, *m.User, error)
}

View File

@@ -22,10 +22,20 @@ import (
===================================
TO SET DATABASE INFO FROM TERMINAL
===================================
=======
MongoDB
=======
set mongo_url=mongodb://localhost:27017/local
set mongo_timeout=10
set mongo_db=local
set url_db=mongo
=======
MySQL
=======
set mysql_url=root:Password.1@tcp(127.0.0.1:3306)/tes
set mysql_timeout=10
set mysql_db=tes
set url_db=mysql
*/
var (

View File

@@ -3,8 +3,10 @@
package services_test
import (
"fmt"
"sync"
"testing"
"time"
"github.com/rinosukmandityo/hexagonal-login/logic"
m "github.com/rinosukmandityo/hexagonal-login/models"
@@ -21,10 +23,20 @@ import (
===================================
TO SET DATABASE INFO FROM TERMINAL
===================================
=======
MongoDB
=======
set mongo_url=mongodb://localhost:27017/local
set mongo_timeout=10
set mongo_db=local
set url_db=mongo
=======
MySQL
=======
set mysql_url=root:Password.1@tcp(127.0.0.1:3306)/tes
set mysql_timeout=10
set mysql_db=tes
set url_db=mysql
*/
var (
@@ -66,6 +78,7 @@ func init() {
}
func TestUserService(t *testing.T) {
// t.Run("Delete All", DeleteAll)
t.Run("Insert User", InsertUser)
t.Run("Update User", UpdateUser)
t.Run("Delete User", DeleteUser)
@@ -85,6 +98,7 @@ func InsertUser(t *testing.T) {
}(data)
}
wg.Wait()
time.Sleep(time.Second * 1)
t.Run("Case 1: Save data", func(t *testing.T) {
for _, data := range testdata {
@@ -98,6 +112,7 @@ func InsertUser(t *testing.T) {
}
wg.Wait()
time.Sleep(time.Second * 1)
for _, data := range testdata {
res, e := userService.GetById(data.ID)
if e != nil || res.ID == "" {
@@ -172,3 +187,11 @@ func GetUser(t *testing.T) {
}
})
}
func DeleteAll(t *testing.T) {
for i := 1; i <= 4; i++ {
data := UserTestData()[0]
data.ID = fmt.Sprintf("userid0%d", i)
userService.Delete(&data)
}
}