質問編集履歴
5
コード全文記載
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
|
-
|
236
|
+
func (ur *userRepository) UpdateUser(user *model.User, userId uint, path string) error {
|
106
|
-
//localの.envを読み込み
|
107
|
-
|
237
|
+
result := ur.db.Model(&user).Clauses(clause.Returning{}).Where("id=?", userId).Updates(model.User{Name: user.Name, Email: user.Email, ImgPath: path})
|
108
|
-
|
238
|
+
if result.Error != nil {
|
109
|
-
|
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
|
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
コード追記
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のバージョンとコードの記載追加
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
該当ソース追加
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
タイトル変更
test
CHANGED
@@ -1 +1 @@
|
|
1
|
-
Golangのunitテストのエラー
|
1
|
+
Golangのunitテストで、transactionのエラーが発生する。
|
test
CHANGED
File without changes
|