質問編集履歴

5

コード全文記載

2023/09/21 12:34

投稿

hajimeeeee
hajimeeeee

スコア3

test CHANGED
File without changes
test CHANGED
@@ -35,6 +35,124 @@
35
35
 
36
36
  ```golang
37
37
  //user_repository_test.go
38
+
39
+ var storedUser = &model.User{
40
+ ID: 1,
41
+ Name: "田中太郎",
42
+ Email: "tanaka@test.com",
43
+ Password: "password",
44
+ ImgPath: "tanaka.png",
45
+ RefreshToken: "refreshtoken",
46
+ CreatedAt: time.Now(),
47
+ UpdatedAt: time.Now(),
48
+ DeletedAt: gorm.DeletedAt{},
49
+ }
50
+
51
+ func TestGetUserByEmail(t *testing.T) {
52
+ t.Run("正常系:Emailからユーザー情報を取得できる",
53
+ func(t *testing.T) {
54
+ database, gormDB, mock, err := NewDbMock()
55
+ defer database.Close()
56
+ assert.NoError(t, err)
57
+ // SQL、引数、戻り値が意図したものであることを期待する
58
+ mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "users" WHERE email=$1 AND "users"."deleted_at" IS NULL ORDER BY "users"."id" LIMIT 1`)).
59
+ WithArgs(storedUser.Email).
60
+ WillReturnRows(sqlmock.NewRows([]string{"id", "name", "email", "password", "img_path"}).AddRow(storedUser.ID, storedUser.Name, storedUser.Email, storedUser.Password, storedUser.ImgPath))
61
+
62
+ ur := NewUserRepository(gormDB)
63
+ user := model.User{}
64
+ err = ur.GetUserByEmail(&user, storedUser.Email)
65
+ assert.NoError(t, err)
66
+ assert.Equal(t, user.ID, storedUser.ID)
67
+ assert.Equal(t, user.Name, storedUser.Name)
68
+ assert.Equal(t, user.Email, storedUser.Email)
69
+ assert.Equal(t, user.Password, storedUser.Password)
70
+ assert.Equal(t, user.ImgPath, storedUser.ImgPath)
71
+ assert.NoError(t, mock.ExpectationsWereMet())
72
+ })
73
+
74
+ t.Run("異常系:存在しないEmailでエラーを返す",
75
+ func(t *testing.T) {
76
+ database, gormDB, mock, err := NewDbMock()
77
+ defer database.Close()
78
+ assert.NoError(t, err)
79
+
80
+ mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "users" WHERE email=$1 AND "users"."deleted_at" IS NULL ORDER BY "users"."id" LIMIT 1`)).
81
+ WithArgs("tanaka@test.com").WillReturnError(gorm.ErrRecordNotFound)
82
+ ur := NewUserRepository(gormDB)
83
+ user := model.User{}
84
+ err = ur.GetUserByEmail(&user, storedUser.Email)
85
+ assert.EqualError(t, err, "Code: no_rows, Msg: failed to find user: record not found")
86
+ })
87
+
88
+ t.Run("異常系:サーバーエラーを返す",
89
+ func(t *testing.T) {
90
+ database, gormDB, mock, err := NewDbMock()
91
+ defer database.Close()
92
+ assert.NoError(t, err)
93
+
94
+ mock.ExpectQuery(regexp.QuoteMeta(`SELECT * FROM "users" WHERE email=$1 AND "users"."deleted_at" IS NULL ORDER BY "users"."id" LIMIT 1`)).
95
+ WithArgs("tanaka@test.com").WillReturnError(gorm.ErrInvalidDB)
96
+ ur := NewUserRepository(gormDB)
97
+ user := model.User{}
98
+ err = ur.GetUserByEmail(&user, storedUser.Email)
99
+ assert.EqualError(t, err, "Code: internal_server, Msg: find user failed by internal server error: invalid db")
100
+ })
101
+ }
102
+
103
+ func TestCreateUser(t *testing.T) {
104
+ t.Run("正常系:ユーザー情報を登録できる",
105
+ func(t *testing.T) {
106
+ user := &model.User{
107
+ Name: "齊藤元",
108
+ Email: "insert@test.com",
109
+ Password: "password",
110
+ ImgPath: "saito.png",
111
+ Role: 9,
112
+ RefreshToken: "",
113
+ CreatedAt: time.Now(),
114
+ UpdatedAt: time.Now(),
115
+ DeletedAt: gorm.DeletedAt{},
116
+ }
117
+
118
+ database, gormDB, mock, err := NewDbMock()
119
+ defer database.Close()
120
+ assert.NoError(t, err)
121
+ mock.ExpectBegin()
122
+ mock.ExpectQuery(regexp.QuoteMeta(`INSERT INTO "users" ("name","email","password","img_path","role","refresh_token","deleted_at","created_at","updated_at") VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9) RETURNING "created_at","updated_at","id"`)).
123
+ WithArgs(user.Name, user.Email, user.Password, user.ImgPath, user.Role, user.RefreshToken, user.DeletedAt, user.CreatedAt, user.UpdatedAt).
124
+ WillReturnRows(sqlmock.NewRows([]string{"created_at", "updated_at", "id"}).AddRow(user.CreatedAt, user.UpdatedAt, 2))
125
+ mock.ExpectCommit()
126
+ ur := NewUserRepository(gormDB)
127
+ err = ur.CreateUser(user)
128
+ assert.NoError(t, err)
129
+ })
130
+ }
131
+
132
+ func TestUpdateUser(t *testing.T) {
133
+ t.Run("正常系:ユーザー情報を更新できる",
134
+ func(t *testing.T) {
135
+ user := &model.User{
136
+ ID: 1,
137
+ Email: "update@test.com",
138
+ ImgPath: "update.png",
139
+ }
140
+ database, gormDB, mock, err := NewDbMock()
141
+ defer database.Close()
142
+ assert.NoError(t, err)
143
+ mock.ExpectBegin()
144
+ mock.ExpectQuery(regexp.QuoteMeta(`UPDATE "users" SET "email"=$1,"img_path"=$2,"updated_at"=$3 WHERE id=$4 AND "users"."deleted_at" IS NULL AND "id" = $5 RETURNING *`)).
145
+ WithArgs(user.Email, user.ImgPath, AnyTime{}, user.ID, user.ID).
146
+ WillReturnRows(sqlmock.NewRows([]string{"email"}).AddRow(user.Email))
147
+ mock.ExpectCommit()
148
+
149
+ ur := NewUserRepository(gormDB)
150
+ err = ur.UpdateUser(user, user.ID, user.ImgPath)
151
+ assert.NoError(t, err)
152
+ assert.NoError(t, mock.ExpectationsWereMet())
153
+ })
154
+
155
+ }
38
156
 
39
157
  func TestSaveRefreshToken(t *testing.T) {
40
158
  t.Run("正常系:リフレッシュトークンを保存できる", func(t *testing.T) {
@@ -62,7 +180,12 @@
62
180
  ```golang
63
181
  //user_repository.go
64
182
 
183
+ package repository
184
+
65
185
  type IUserRepository interface {
186
+ GetUserByEmail(user *model.User, email string) error
187
+ CreateUser(user *model.User) error
188
+ UpdateUser(user *model.User, userId uint, path string) error
66
189
  SaveRefreshToken(user *model.User, userId uint, refreshToken string) error
67
190
  }
68
191
 
@@ -72,6 +195,31 @@
72
195
 
73
196
  func NewUserRepository(db *gorm.DB) IUserRepository {
74
197
  return &userRepository{db}
198
+ }
199
+
200
+ func (ur *userRepository) GetUserByEmail(user *model.User, email string) error {
201
+ if err := ur.db.Where("email=?", email).First(&user).Error; err != nil {
202
+ if errors.Is(err, gorm.ErrRecordNotFound) {
203
+ return API.Errorf(code.NoRows, "failed to find user: %s", err)
204
+ }
205
+ return API.Errorf(code.InternalServer, "find user failed by internal server error: %s", err)
206
+ }
207
+ fmt.Print("user: ", user)
208
+ return nil
209
+ }
210
+
211
+ func (ur *userRepository) CreateUser(user *model.User) error {
212
+ if err := ur.db.Create(user).Error; err != nil {
213
+ var pgErr *pgconn.PgError
214
+ if errors.As(err, &pgErr) {
215
+ if pgErr.Code == pgerrcode.UniqueViolation || pgErr.Code == pgerrcode.ForeignKeyViolation {
216
+ return API.Errorf(code.Forbidden, "create user failed by forbidden error: %s", err)
217
+ }
218
+ }
219
+ return API.Errorf(code.InternalServer, "create user failed by internal server error: %s", err)
220
+ }
221
+ fmt.Print("user: ", user)
222
+ return nil
75
223
  }
76
224
 
77
225
  func (ur *userRepository) SaveRefreshToken(user *model.User, userId uint, refreshToken string) error {
@@ -84,54 +232,16 @@
84
232
  }
85
233
  return nil
86
234
  }
87
- ```
235
+
88
-
89
- ```golang
90
- //db.go
91
- package db
92
-
93
- import (
94
- "fmt"
95
- "github.com/joho/godotenv"
96
- "gorm.io/driver/postgres"
97
- "gorm.io/gorm"
98
- "gorm.io/gorm/logger"
99
- "log"
100
- "os"
101
- )
102
-
103
- func NewDB() *gorm.DB {
104
- //dev環境かどうか
105
- if os.Getenv("GO_ENV") == "dev" {
236
+ func (ur *userRepository) UpdateUser(user *model.User, userId uint, path string) error {
106
- //localの.envを読み込み
107
- err := godotenv.Load()
237
+ result := ur.db.Model(&user).Clauses(clause.Returning{}).Where("id=?", userId).Updates(model.User{Name: user.Name, Email: user.Email, ImgPath: path})
108
- if err != nil {
238
+ if result.Error != nil {
109
- log.Fatalln("read .env:", err)
239
+ return API.Errorf(code.InternalServer, "failed to update user by internal server error: %s", result.Error)
110
- }
240
+ }
241
+ if result.RowsAffected < 1 {
242
+ return API.Errorf(code.NoRows, "failed to update user by no rows")
111
- }
243
+ }
112
- //DBに接続するコマンド生成
113
- url := fmt.Sprintf("postgres://%s:%s@%s:%s/%s",
114
- os.Getenv("DB_USER"), os.Getenv("DB_PASS"), os.Getenv("DB_HOST"), os.Getenv("DB_PORT"), os.Getenv("DB_NAME"))
115
-
116
- //DB接続
117
- fmt.Println(url)
118
- db, err := gorm.Open(postgres.Open(url), &gorm.Config{})
119
- if err != nil {
120
- log.Fatalln("new db:", err)
121
- }
122
- fmt.Println("connected")
123
-
124
- if os.Getenv("GO_ENV") == "dev" {
125
- db.Logger = db.Logger.LogMode(logger.Info)
126
- }
127
- return db
244
+ return nil
128
- }
129
-
130
- func CloseDB(db *gorm.DB) {
131
- sqlDB, _ := db.DB()
132
- if err := sqlDB.Close(); err != nil {
133
- log.Fatalln("close db:", err)
134
- }
135
245
  }
136
246
 
137
247
  ```
@@ -139,15 +249,6 @@
139
249
  //test_config.go
140
250
 
141
251
  package repository
142
-
143
- import (
144
- "database/sql"
145
- "database/sql/driver"
146
- "github.com/DATA-DOG/go-sqlmock"
147
- "gorm.io/driver/postgres"
148
- "gorm.io/gorm"
149
- "time"
150
- )
151
252
 
152
253
  type AnyTime struct{}
153
254
 

4

コード追記

2023/09/21 12:19

投稿

hajimeeeee
hajimeeeee

スコア3

test CHANGED
File without changes
test CHANGED
@@ -62,6 +62,18 @@
62
62
  ```golang
63
63
  //user_repository.go
64
64
 
65
+ type IUserRepository interface {
66
+ SaveRefreshToken(user *model.User, userId uint, refreshToken string) error
67
+ }
68
+
69
+ type userRepository struct {
70
+ db *gorm.DB
71
+ }
72
+
73
+ func NewUserRepository(db *gorm.DB) IUserRepository {
74
+ return &userRepository{db}
75
+ }
76
+
65
77
  func (ur *userRepository) SaveRefreshToken(user *model.User, userId uint, refreshToken string) error {
66
78
  result := ur.db.Updates(user).Where("id=?", userId).Update("refresh_token", refreshToken)
67
79
  if result.Error != nil {
@@ -71,10 +83,6 @@
71
83
  return API.Errorf(code.NoRows, "failed to save refresh_token by no rows")
72
84
  }
73
85
  return nil
74
- }
75
-
76
- func NewUserRepository(db *gorm.DB) IUserRepository {
77
- return &userRepository{db}
78
86
  }
79
87
  ```
80
88
 

3

gormのバージョンとコードの記載追加

2023/09/21 12:15

投稿

hajimeeeee
hajimeeeee

スコア3

test CHANGED
File without changes
test CHANGED
@@ -72,8 +72,61 @@
72
72
  }
73
73
  return nil
74
74
  }
75
+
76
+ func NewUserRepository(db *gorm.DB) IUserRepository {
77
+ return &userRepository{db}
78
+ }
75
79
  ```
76
80
 
81
+ ```golang
82
+ //db.go
83
+ package db
84
+
85
+ import (
86
+ "fmt"
87
+ "github.com/joho/godotenv"
88
+ "gorm.io/driver/postgres"
89
+ "gorm.io/gorm"
90
+ "gorm.io/gorm/logger"
91
+ "log"
92
+ "os"
93
+ )
94
+
95
+ func NewDB() *gorm.DB {
96
+ //dev環境かどうか
97
+ if os.Getenv("GO_ENV") == "dev" {
98
+ //localの.envを読み込み
99
+ err := godotenv.Load()
100
+ if err != nil {
101
+ log.Fatalln("read .env:", err)
102
+ }
103
+ }
104
+ //DBに接続するコマンド生成
105
+ url := fmt.Sprintf("postgres://%s:%s@%s:%s/%s",
106
+ os.Getenv("DB_USER"), os.Getenv("DB_PASS"), os.Getenv("DB_HOST"), os.Getenv("DB_PORT"), os.Getenv("DB_NAME"))
107
+
108
+ //DB接続
109
+ fmt.Println(url)
110
+ db, err := gorm.Open(postgres.Open(url), &gorm.Config{})
111
+ if err != nil {
112
+ log.Fatalln("new db:", err)
113
+ }
114
+ fmt.Println("connected")
115
+
116
+ if os.Getenv("GO_ENV") == "dev" {
117
+ db.Logger = db.Logger.LogMode(logger.Info)
118
+ }
119
+ return db
120
+ }
121
+
122
+ func CloseDB(db *gorm.DB) {
123
+ sqlDB, _ := db.DB()
124
+ if err := sqlDB.Close(); err != nil {
125
+ log.Fatalln("close db:", err)
126
+ }
127
+ }
128
+
129
+ ```
77
130
  ```golang
78
131
  //test_config.go
79
132
 
@@ -112,4 +165,6 @@
112
165
  github.com/DATA-DOG/go-sqlmock v1.5.0
113
166
  github.com/stretchr/testify v1.8.4
114
167
  testing
168
+ gorm.io/driver/postgres v1.5.2
169
+ gorm.io/gorm v1.25.2
115
170
 

2

該当ソース追加

2023/09/20 14:18

投稿

hajimeeeee
hajimeeeee

スコア3

test CHANGED
File without changes
test CHANGED
@@ -32,6 +32,32 @@
32
32
  ```
33
33
 
34
34
  ### 該当のソースコード
35
+
36
+ ```golang
37
+ //user_repository_test.go
38
+
39
+ func TestSaveRefreshToken(t *testing.T) {
40
+ t.Run("正常系:リフレッシュトークンを保存できる", func(t *testing.T) {
41
+ user := &model.User{
42
+ DeletedAt: gorm.DeletedAt{},
43
+ ID: 2,
44
+ RefreshToken: "refreshtoken",
45
+ UpdatedAt: time.Now(),
46
+ }
47
+ _, gormDB, mock, err := NewDbMock()
48
+ assert.NoError(t, err)
49
+ mock.ExpectBegin()
50
+ mock.ExpectExec(regexp.QuoteMeta(`UPDATE "users" SET "refresh_token"=$1,"updated_at"=$2 WHERE "users"."deleted_at" IS NULL AND "id" = $3`)).
51
+ WithArgs(user.RefreshToken, AnyTime{}, user.ID).
52
+ WillReturnResult(sqlmock.NewResult(0, 1)) // RowsAffectedが1を返すように修正
53
+ mock.ExpectCommit()
54
+ ur := NewUserRepository(gormDB)
55
+ err = ur.SaveRefreshToken(user, user.ID, user.RefreshToken)
56
+ assert.NoError(t, err)
57
+ assert.NoError(t, mock.ExpectationsWereMet())
58
+ })
59
+ }
60
+ ```
35
61
 
36
62
  ```golang
37
63
  //user_repository.go

1

タイトル変更

2023/09/20 09:57

投稿

hajimeeeee
hajimeeeee

スコア3

test CHANGED
@@ -1 +1 @@
1
- Golangのunitテストのエラーを解決したい
1
+ Golangのunitテストで、transactionのエラーが発生する
test CHANGED
File without changes