Skip to content

Commit 4f3f4dc

Browse files
committed
Fix validation issues and ignore some of them
1 parent 390ebdb commit 4f3f4dc

File tree

9 files changed

+53
-35
lines changed

9 files changed

+53
-35
lines changed

.golangci.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,15 @@ linters:
127127
- lll
128128
- depguard
129129
- revive
130+
- wrapcheck
131+
- tagliatelle
132+
- exhaustruct
133+
- testpackage
134+
- mnd
135+
- gochecknoinits
136+
- gochecknoglobals
137+
- forcetypeassert
138+
- ireturn
130139

131140
issues:
132141
max-same-issues: 0

controller/status_errors.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package controller
22

33
import (
4+
"errors"
45
"go-api-template/model"
56
"go-api-template/model/commonerrors"
67
"go-api-template/pkg/json"
@@ -105,7 +106,8 @@ func StatusForbidden(ctx *gin.Context, message string) {
105106

106107
// handleCommonErrors handles common errors and returns appropriate HTTP status codes.
107108
func HandleCommonErrors(ctx *gin.Context, err error) {
108-
if _, ok := err.(*commonerrors.CommonError); ok {
109+
var commonErr *commonerrors.CommonError
110+
if errors.As(err, &commonErr) {
109111
StatusUnprocessableEntity(ctx, err)
110112

111113
return

controller/user_test.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ func (suite *UserTestSuite) TearDownTest() {
4343
}
4444

4545
func Test_User_TestSuite(t *testing.T) {
46+
t.Parallel() // Enable parallel execution
4647
suite.Run(t, &UserTestSuite{})
4748
}
4849

@@ -57,11 +58,11 @@ func (suite *UserTestSuite) Test_UserByID_ReturnsBadRequest_InCaseOfUserIDIsNotV
5758
suite.controller.UserByID(suite.ctx)
5859

5960
// Assert
60-
suite.Equal(http.StatusBadRequest, suite.responseRecorder.Code)
61+
suite.Require().Equal(http.StatusBadRequest, suite.responseRecorder.Code)
6162

6263
var actualResponse model.BadRequestResponse
6364
err := json.NewDecoder(suite.responseRecorder.Body).Decode(&actualResponse)
64-
suite.NoError(err)
65+
suite.Require().NoError(err)
6566
suite.Equal(commonerrors.ErrInvalidUserID.Error(), actualResponse.Message)
6667
}
6768

@@ -79,11 +80,11 @@ func (suite *UserTestSuite) Test_UserByID_ReturnsUnprocessableEntity_InCaseOfUse
7980
suite.controller.UserByID(suite.ctx)
8081

8182
// Assert
82-
suite.Equal(http.StatusUnprocessableEntity, suite.responseRecorder.Code)
83+
suite.Require().Equal(http.StatusUnprocessableEntity, suite.responseRecorder.Code)
8384

8485
var actualResponse model.UnprocessableEntityResponse
8586
err := json.NewDecoder(suite.responseRecorder.Body).Decode(&actualResponse)
86-
suite.NoError(err)
87+
suite.Require().NoError(err)
8788
suite.Equal(commonerrors.ErrUserNotFound.Error(), actualResponse.Message)
8889
}
8990

@@ -107,10 +108,10 @@ func (suite *UserTestSuite) Test_UserByID_ReturnsResponse_InCaseOfSuccess() {
107108
suite.controller.UserByID(suite.ctx)
108109

109110
// Assert
110-
suite.Equal(http.StatusOK, suite.responseRecorder.Code)
111+
suite.Require().Equal(http.StatusOK, suite.responseRecorder.Code)
111112

112113
var actualResponse model.UserByIDResponse
113114
err := json.NewDecoder(suite.responseRecorder.Body).Decode(&actualResponse)
114-
suite.NoError(err)
115+
suite.Require().NoError(err)
115116
suite.Equal(expectedResponse, &actualResponse)
116117
}

middleware/router.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
package middleware
22

33
import (
4-
"errors"
54
"go-api-template/configuration"
65
"go-api-template/controller"
6+
"go-api-template/model/commonerrors"
77
"go-api-template/pkg/logger"
88

99
"github.com/gin-gonic/gin"
@@ -37,7 +37,7 @@ func authorizationHeaderRequired() gin.HandlerFunc {
3737
return func(ctx *gin.Context) {
3838
token := ctx.GetHeader("Authorization")
3939
if token == "" {
40-
controller.StatusUnauthorized(ctx, errors.New("authorization header required"))
40+
controller.StatusUnauthorized(ctx, commonerrors.ErrAuthorizationHeaderRequired)
4141
ctx.Abort()
4242

4343
return

model/commonerrors/errors.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,12 @@ func (e *CommonError) Error() string {
1010
return e.Err.Error()
1111
}
1212

13+
//nolint: err113
1314
var (
14-
ErrUserNotFound = &CommonError{Err: errors.New("user not found")}
15-
ErrInvalidUserID = &CommonError{Err: errors.New("invalid user ID")}
15+
ErrFailed = &CommonError{Err: errors.New("failed")}
16+
ErrUserNotFound = &CommonError{Err: errors.New("user not found")}
17+
ErrInvalidUserID = &CommonError{Err: errors.New("invalid user ID")}
18+
ErrAuthorizationHeaderRequired = &CommonError{Err: errors.New("authorization header required")}
1619
)
1720

1821
// Add other common errors here

pkg/random/string.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ import (
88
uuid "github.com/nu7hatch/gouuid"
99
)
1010

11-
func String(n int) string {
12-
bytes := make([]byte, n)
11+
func String(stringLength int) string {
12+
bytes := make([]byte, stringLength)
1313
if _, err := rand.Read(bytes); err != nil {
1414
return ""
1515
}
1616

17-
return hex.EncodeToString(bytes)[:n]
17+
return hex.EncodeToString(bytes)[:stringLength]
1818
}
1919

2020
func UUID4() strfmt.UUID4 {

repository/connection.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55
"go-api-template/configuration"
66
"go-api-template/pkg/logger"
7+
"net"
78

89
"github.com/jmoiron/sqlx"
910
_ "github.com/lib/pq" // driver for PostgreSQL
@@ -14,28 +15,28 @@ type Connection struct {
1415
}
1516

1617
func NewConnection(cfg *configuration.Env) *Connection {
17-
psqlURL := fmt.Sprintf("postgres://%s:%s@%s:%s/%s?sslmode=%s",
18+
hostPort := net.JoinHostPort(cfg.PostgresHost, cfg.PostgresPort)
19+
psqlURL := fmt.Sprintf("postgres://%s:%s@%s/%s?sslmode=%s",
1820
cfg.PostgresUser,
1921
cfg.PostgresPassword,
20-
cfg.PostgresHost,
21-
cfg.PostgresPort,
22+
hostPort,
2223
cfg.PostgresDB,
2324
cfg.PostgresSSLMode,
2425
)
2526

26-
db, err := sqlx.Open("postgres", psqlURL)
27+
database, err := sqlx.Open("postgres", psqlURL)
2728
if err != nil {
2829
logger.Fatalf("connecting to database failed. %v", err)
2930
}
3031

31-
if err = db.Ping(); err != nil {
32+
if err = database.Ping(); err != nil {
3233
logger.Fatalf("connecting to database failed. %v", err)
3334
}
3435

3536
logger.Infof("database connection established")
3637

3738
return &Connection{
38-
db: db,
39+
db: database,
3940
}
4041
}
4142

repository/user_test.go

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package repository
22

33
import (
44
"database/sql"
5-
"errors"
65
"go-api-template/model/commonerrors"
76
"go-api-template/pkg/random"
87
"go-api-template/repository/model"
@@ -35,26 +34,29 @@ func (suite *UserTestSuite) SetupTest() {
3534
suite.db = sqlx.NewDb(db, "sqlmock")
3635
suite.repository = NewUser(suite.db)
3736
suite.userID = random.UUID4()
38-
suite.failedError = errors.New("failed")
37+
suite.failedError = commonerrors.ErrFailed
3938
}
4039

4140
func (suite *UserTestSuite) TearDownTest() {
42-
suite.db.Close()
41+
if err := suite.db.Close(); err != nil {
42+
suite.T().Errorf("closing database connection failed. %v", err)
43+
}
4344
}
4445

4546
func Test_User_TestSuite(t *testing.T) {
47+
t.Parallel() // Enable parallel execution
4648
suite.Run(t, &UserTestSuite{})
4749
}
4850

4951
func (suite *UserTestSuite) Test_Begin_ReturnsError_InCaseOfBeginFailed() {
5052
// Arrange
51-
suite.dbMock.ExpectBegin().WillReturnError(errors.New("failed"))
53+
suite.dbMock.ExpectBegin().WillReturnError(suite.failedError)
5254

5355
// Act
5456
_, err := suite.repository.Begin()
5557

5658
// Assert
57-
suite.Error(err)
59+
suite.Require().Error(err)
5860
}
5961

6062
func (suite *UserTestSuite) Test_Begin_ReturnsTransaction_InCaseOfSuccess() {
@@ -65,7 +67,7 @@ func (suite *UserTestSuite) Test_Begin_ReturnsTransaction_InCaseOfSuccess() {
6567
tx, err := suite.repository.Begin()
6668

6769
// Assert
68-
suite.NoError(err)
70+
suite.Require().NoError(err)
6971
suite.NotNil(tx)
7072
}
7173

@@ -75,13 +77,13 @@ func (suite *UserTestSuite) Test_SelectUserByFilter_ReturnsError_InCaseOfSelectF
7577
ID: &suite.userID,
7678
}
7779

78-
suite.dbMock.ExpectQuery("SELECT").WillReturnError(errors.New("failed"))
80+
suite.dbMock.ExpectQuery("SELECT").WillReturnError(suite.failedError)
7981

8082
// Act
8183
_, err := suite.repository.SelectUserByFilter(usersFilter)
8284

8385
// Assert
84-
suite.Error(err)
86+
suite.Require().Error(err)
8587
}
8688

8789
func (suite *UserTestSuite) Test_SelectUserByFilter_ReturnsError_InCaseOfUserNotFound() {
@@ -96,7 +98,7 @@ func (suite *UserTestSuite) Test_SelectUserByFilter_ReturnsError_InCaseOfUserNot
9698
_, err := suite.repository.SelectUserByFilter(usersFilter)
9799

98100
// Assert
99-
suite.Error(err)
101+
suite.Require().Error(err)
100102
suite.Equal(commonerrors.ErrUserNotFound, err)
101103
}
102104

@@ -114,7 +116,7 @@ func (suite *UserTestSuite) Test_SelectUserByFilter_ReturnsUser_InCaseOfSuccess(
114116
user, err := suite.repository.SelectUserByFilter(usersFilter)
115117

116118
// Assert
117-
suite.NoError(err)
119+
suite.Require().NoError(err)
118120
suite.NotNil(user)
119121
suite.Equal(suite.userID, user.ID)
120122
}

service/user_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package service
22

33
import (
4-
"errors"
54
"go-api-template/model/commonerrors"
65
"go-api-template/pkg/random"
76
"go-api-template/repository"
@@ -32,14 +31,15 @@ func (suite *UserTestSuite) SetupTest() {
3231
suite.userRepositoryMock = &repository.UserMock{}
3332
suite.service = NewUser(suite.userRepositoryMock)
3433
suite.userID = random.UUID4()
35-
suite.failedError = errors.New("failed")
34+
suite.failedError = commonerrors.ErrFailed
3635
}
3736

3837
func (suite *UserTestSuite) TearDownTest() {
3938
suite.userRepositoryMock.AssertExpectations(suite.T())
4039
}
4140

4241
func Test_User_TestSuite(t *testing.T) {
42+
t.Parallel() // Enable parallel execution
4343
suite.Run(t, &UserTestSuite{})
4444
}
4545

@@ -58,7 +58,7 @@ func (suite *UserTestSuite) Test_UserByID_ReturnsError_InCaseOfSelectUserByFilte
5858
response, err := suite.service.UserByID(suite.ctx, suite.userID)
5959

6060
// Assert
61-
suite.Nil(response)
61+
suite.Require().Nil(response)
6262

6363
if suite.Error(err) {
6464
suite.Equal(suite.failedError, err)
@@ -80,7 +80,7 @@ func (suite *UserTestSuite) Test_UserByID_ReturnsError_InCaseOfUserNotFound() {
8080
response, err := suite.service.UserByID(suite.ctx, suite.userID)
8181

8282
// Assert
83-
suite.Nil(response)
83+
suite.Require().Nil(response)
8484

8585
if suite.Error(err) {
8686
suite.Equal(commonerrors.ErrUserNotFound, err)
@@ -106,7 +106,7 @@ func (suite *UserTestSuite) Test_UserByID_ReturnsUser_InCaseOfSuccess() {
106106
response, err := suite.service.UserByID(suite.ctx, suite.userID)
107107

108108
// Assert
109-
suite.NoError(err)
109+
suite.Require().NoError(err)
110110

111111
if suite.NotNil(response) {
112112
suite.Equal(user.ID, response.User.ID)

0 commit comments

Comments
 (0)