Skip to content

Commit

Permalink
Merge pull request #61 from go-park-mail-ru/OZON-166
Browse files Browse the repository at this point in the history
[OZON-166] Тесты для usecase
  • Loading branch information
JOJOSoderqvist authored Dec 18, 2024
2 parents 74f57db + 2a14d15 commit f603644
Show file tree
Hide file tree
Showing 58 changed files with 3,351 additions and 1,553 deletions.
8 changes: 6 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,12 @@ test:

test-coverage:
go test ./... -coverprofile=coverage.out
go tool cover -func=coverage.out
go tool cover -html=coverage.out
# Exclude protobuf 'gen' directories, 'docs', 'internal/errs', and 'dto_easyjson.go' files
grep -vE '\/kafka_api\/|\/grpc_api\/|\/metrics\/|\/middlewares\/|\/configs\/|\/apps\/|\/cmd\/|\/mocks\/|\/gen\/|\/docs\/|\/internal\/errs\/|dto_easyjson\.go|init\.go' coverage.out > coverage_filtered.out
go tool cover -func=coverage_filtered.out
go tool cover -html=coverage_filtered.out



PROTO_DIR := ./api/protos

Expand Down
3 changes: 0 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,10 @@ module github.com/go-park-mail-ru/2024_2_kotyari
go 1.23.1

require (
github.com/bxcodec/faker/v3 v3.8.1
github.com/bxcodec/faker/v4 v4.0.0-beta.3
github.com/caarlos0/env v3.5.0+incompatible
github.com/disintegration/imaging v1.6.2
github.com/go-faker/faker/v4 v4.5.0
github.com/go-redis/redismock/v9 v9.2.0
github.com/golang/mock v1.6.0
github.com/golang/protobuf v1.5.4
github.com/google/uuid v1.6.0
github.com/gorilla/mux v1.8.1
Expand Down
4 changes: 0 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
github.com/bxcodec/faker/v3 v3.8.1 h1:qO/Xq19V6uHt2xujwpaetgKhraGCapqY2CRWGD/SqcM=
github.com/bxcodec/faker/v3 v3.8.1/go.mod h1:DdSDccxF5msjFo5aO4vrobRQ8nIApg8kq3QWPEQD6+o=
github.com/bxcodec/faker/v4 v4.0.0-beta.3 h1:gqYNBvN72QtzKkYohNDKQlm+pg+uwBDVMN28nWHS18k=
github.com/bxcodec/faker/v4 v4.0.0-beta.3/go.mod h1:m6+Ch1Lj3fqW/unZmvkXIdxWS5+XQWPWxcbbQW2X+Ho=
github.com/caarlos0/env v3.5.0+incompatible h1:Yy0UN8o9Wtr/jGHZDpCBLpNrzcFLLM2yixi/rBrKyJs=
Expand All @@ -35,8 +33,6 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/go-faker/faker/v4 v4.5.0 h1:ARzAY2XoOL9tOUK+KSecUQzyXQsUaZHefjyF8x6YFHc=
github.com/go-faker/faker/v4 v4.5.0/go.mod h1:p3oq1GRjG2PZ7yqeFFfQI20Xm61DoBDlCA8RiSyZ48M=
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
Expand Down
2 changes: 1 addition & 1 deletion internal/apps/notifications/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func (n *NotificationsApp) Run() error {
return err
}

n.log.Info("[NotificationsApp.Run] Server started listening at: ", n.config.Port)
n.log.Info("[NotificationsApp.Run] Server started listening at: ", slog.String("port", n.config.Port))

if err = n.server.Serve(listener); err != nil {
n.log.Info("[NotificationsApp.Run] Failed to start listening",
Expand Down
6 changes: 3 additions & 3 deletions internal/apps/rating_updater/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ func NewApp(config map[string]any) (*RatingUpdaterApp, error) {
slogLogger := logger.InitLogger()

if err != nil {
slogLogger.Error("[RatingUpdaterApp] Failed to load dbPool", err.Error())
slogLogger.Error("[RatingUpdaterApp] Failed to load dbPool", slog.String("error", err.Error()))

return nil, err
}
Expand All @@ -62,7 +62,7 @@ func NewApp(config map[string]any) (*RatingUpdaterApp, error) {

go func() {
if err := serverProm.ListenAndServe(); err != nil {
slogLogger.Error("fail auth.ListenAndServe")
slogLogger.Error("fail auth.ListenAndServe", slog.String("error", err.Error()))
}
}()
productsRepo := productRepoLib.NewProductsStore(dbPool, slogLogger)
Expand All @@ -73,7 +73,7 @@ func NewApp(config map[string]any) (*RatingUpdaterApp, error) {

cfg, err := configs.ParseServiceViperConfig(config)
if err != nil {
log.Error("RatingUpdaterApp [NewApp] Failed to parse viper config")
slogLogger.Error("RatingUpdaterApp [NewApp] Failed to parse viper config")

return nil, err
}
Expand Down
267 changes: 267 additions & 0 deletions internal/delivery/address/address_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,267 @@
package address

import (
"context"
"errors"
"github.com/go-park-mail-ru/2024_2_kotyari/internal/delivery/address/mocks"
"github.com/go-park-mail-ru/2024_2_kotyari/internal/errs"
"github.com/go-park-mail-ru/2024_2_kotyari/internal/model"
"github.com/go-park-mail-ru/2024_2_kotyari/internal/utils"
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
"go.uber.org/mock/gomock"
"io"
"log/slog"
"net/http"
"net/http/httptest"
"strings"
"testing"
)

const testContextRequestIDKey = "request-id"

var (
testContextRequestIDValue = uuid.New()
)

func TestAddressDelivery_GetAddress(t *testing.T) {
type want struct {
statusCode int
response string
}

tests := []struct {
name string
setupFunc func(ctrl *gomock.Controller) *AddressDelivery
request *http.Request
want want
}{
{
name: "Успешное выполнение",
setupFunc: func(ctrl *gomock.Controller) *AddressDelivery {
addressManager := mocks.NewMockaddressManager(ctrl)

addressManager.EXPECT().
GetAddressByProfileID(gomock.Any(), uint32(1)).
Return(model.Address{Text: "Main St"}, nil)

logger := slog.New(slog.NewTextHandler(io.Discard, nil))
errResolver := errs.NewErrorStore()
return &AddressDelivery{
addressManager: addressManager,
log: logger,
errResolver: errResolver,
}
},
request: func() *http.Request {
req := httptest.NewRequest(http.MethodGet, "/address", nil)
ctx := utils.SetContextSessionUserID(req.Context(), 1)
return req.WithContext(ctx)
}(),
want: want{
statusCode: http.StatusOK,
response: `{"body":{"address":"Main St"}, "status":200}`,
},
},
{
name: "Пользователь не авторизован",
setupFunc: func(ctrl *gomock.Controller) *AddressDelivery {
logger := slog.New(slog.NewTextHandler(io.Discard, nil))
mockAddressManager := mocks.NewMockaddressManager(ctrl)

//mockAddressManager.
// EXPECT().
// GetAddressByProfileID(gomock.Any(), gomock.Any()).
// Times(1).
// Return(model.Address{}, errs.UserNotAuthorized)

return &AddressDelivery{
log: logger,
errResolver: errs.NewErrorStore(),
addressManager: mockAddressManager,
}
},
request: httptest.NewRequest(http.MethodGet, "/address", nil),
want: want{
statusCode: http.StatusUnauthorized,
response: `{"body":{"error_message":"Пользователь не авторизован"}, "status":401}`,
},
},

{
name: "Ошибка при получении адреса",
setupFunc: func(ctrl *gomock.Controller) *AddressDelivery {
addressManager := mocks.NewMockaddressManager(ctrl)

addressManager.EXPECT().
GetAddressByProfileID(gomock.Any(), uint32(1)).
Return(model.Address{}, errors.New("internal error"))

logger := slog.New(slog.NewTextHandler(io.Discard, nil))
return &AddressDelivery{
addressManager: addressManager,
log: logger,
errResolver: errs.NewErrorStore(),
}
},
request: func() *http.Request {
req := httptest.NewRequest(http.MethodGet, "/address", nil)
ctx := utils.SetContextSessionUserID(req.Context(), 1)
return req.WithContext(ctx)
}(),
want: want{
statusCode: http.StatusInternalServerError,
response: `{"body":{"error_message":"внутренняя ошибка сервера"}, "status":500}`,
},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

addressDelivery := tt.setupFunc(ctrl)
recorder := httptest.NewRecorder()

ctx := context.WithValue(tt.request.Context(), testContextRequestIDKey, testContextRequestIDValue)

reqWithCtx := tt.request.WithContext(ctx)

addressDelivery.GetAddress(recorder, reqWithCtx)

assert.Equal(t, tt.want.statusCode, recorder.Code)
assert.JSONEq(t, tt.want.response, recorder.Body.String())
})
}
}

func TestAddressDelivery_UpdateAddressData(t *testing.T) {
type want struct {
statusCode int
response string
}

tests := []struct {
name string
setupFunc func(ctrl *gomock.Controller) *AddressDelivery
request *http.Request
want want
}{
{
name: "Успешное выполнение",
setupFunc: func(ctrl *gomock.Controller) *AddressDelivery {
addressManager := mocks.NewMockaddressManager(ctrl)
addressManager.EXPECT().
UpdateUsersAddress(gomock.Any(), uint32(1), gomock.Any()).
Return(nil)

logger := slog.New(slog.NewTextHandler(io.Discard, nil))
errResolver := errs.NewErrorStore()
return &AddressDelivery{
addressManager: addressManager,
log: logger,
errResolver: errResolver,
}
},
request: func() *http.Request {
body := `{"address":"New StreetNew City"}`
req := httptest.NewRequest(http.MethodPost, "/address/update", io.NopCloser(strings.NewReader(body)))
ctx := utils.SetContextSessionUserID(req.Context(), 1)
return req.WithContext(ctx)
}(),
want: want{
statusCode: http.StatusOK,
response: `{"body":{"address":"New StreetNew City"}, "status":200}`,
},
},
{
name: "Пользователь не авторизован",
setupFunc: func(ctrl *gomock.Controller) *AddressDelivery {
logger := slog.New(slog.NewTextHandler(io.Discard, nil))
return &AddressDelivery{
log: logger,
errResolver: errs.NewErrorStore(),
addressManager: mocks.NewMockaddressManager(ctrl),
}
},
request: func() *http.Request {
req := httptest.NewRequest(http.MethodPost, "/address/update", nil)
return req // Не нужно добавлять сессию, чтобы эмулировать неавторизованного пользователя
}(),
want: want{
statusCode: http.StatusUnauthorized,
response: `{"body":{"error_message":"Пользователь не авторизован"}, "status":401}`,
},
},

{
name: "Ошибка десериализации JSON",
setupFunc: func(ctrl *gomock.Controller) *AddressDelivery {
logger := slog.New(slog.NewTextHandler(io.Discard, nil))
errResolver := errs.NewErrorStore()
return &AddressDelivery{
log: logger,
errResolver: errResolver,
addressManager: mocks.NewMockaddressManager(ctrl),
}
},
request: func() *http.Request {
body := `{"invalid_json":}`
req := httptest.NewRequest(http.MethodPost, "/address/update", io.NopCloser(strings.NewReader(body)))
ctx := utils.SetContextSessionUserID(req.Context(), 1)
return req.WithContext(ctx)
}(),
want: want{
statusCode: http.StatusBadRequest,
response: `{"body":{"error_message":"Неверный формат JSON"}, "status":400}`,
},
},
{
name: "Ошибка на уровне менеджера",
setupFunc: func(ctrl *gomock.Controller) *AddressDelivery {
addressManager := mocks.NewMockaddressManager(ctrl)
addressManager.EXPECT().
UpdateUsersAddress(gomock.Any(), uint32(1), gomock.Any()).
Return(errors.New("internal error"))

logger := slog.New(slog.NewTextHandler(io.Discard, nil))
errResolver := errs.NewErrorStore()
return &AddressDelivery{
addressManager: addressManager,
log: logger,
errResolver: errResolver,
}
},
request: func() *http.Request {
body := `{"street":"New Street", "city":"New City"}`
req := httptest.NewRequest(http.MethodPost, "/address/update", io.NopCloser(strings.NewReader(body)))
ctx := utils.SetContextSessionUserID(req.Context(), 1)
return req.WithContext(ctx)
}(),
want: want{
statusCode: http.StatusInternalServerError,
response: `{"body":{"error_message":"Внутренняя ошибка сервера"}, "status":500}`,
},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

addressDelivery := tt.setupFunc(ctrl)
recorder := httptest.NewRecorder()

ctx := context.WithValue(tt.request.Context(), testContextRequestIDKey, testContextRequestIDValue)

reqWithCtx := tt.request.WithContext(ctx)

addressDelivery.UpdateAddressData(recorder, reqWithCtx)

assert.Equal(t, tt.want.statusCode, recorder.Code)
assert.JSONEq(t, tt.want.response, recorder.Body.String())
})
}
}
5 changes: 5 additions & 0 deletions internal/delivery/address/get_address.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package address

import (
"errors"
"log/slog"
"net/http"

Expand All @@ -22,12 +23,16 @@ func (h *AddressDelivery) GetAddress(w http.ResponseWriter, r *http.Request) {
userID, ok := utils.GetContextSessionUserID(r.Context())
if !ok {
utils.WriteErrorJSON(w, http.StatusUnauthorized, errs.UserNotAuthorized)

return
}

address, err := h.addressManager.GetAddressByProfileID(r.Context(), userID)

if err != nil {
h.log.Error("[ AddressDelivery.GetAddress ] Ошибка при получении адреса на уровне деливери", slog.String("error", err.Error()))

utils.WriteErrorJSON(w, http.StatusInternalServerError, errors.New("внутренняя ошибка сервера"))
return
}

Expand Down
Loading

0 comments on commit f603644

Please sign in to comment.