add_place_test.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. package place
  2. import (
  3. "context"
  4. "database/sql"
  5. "errors"
  6. "net/http/httptest"
  7. "testing"
  8. API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
  9. "git.dmitriygnatenko.ru/dima/homethings/internal/dto"
  10. "git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
  11. "git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
  12. "git.dmitriygnatenko.ru/dima/homethings/internal/models"
  13. repoMocks "git.dmitriygnatenko.ru/dima/homethings/internal/repositories/mocks"
  14. sp "git.dmitriygnatenko.ru/dima/homethings/internal/service_provider"
  15. "github.com/brianvoe/gofakeit/v6"
  16. "github.com/gofiber/fiber/v2"
  17. "github.com/gojuno/minimock/v3"
  18. "github.com/stretchr/testify/assert"
  19. )
  20. func Test_AddPlaceHandler(t *testing.T) {
  21. type req struct {
  22. method string
  23. route string
  24. contentType string
  25. body *dto.AddPlaceRequest
  26. }
  27. var (
  28. mc = minimock.NewController(t)
  29. placeID = gofakeit.Number(1, 1000)
  30. parentID = gofakeit.Number(1, 1000)
  31. title = gofakeit.Phrase()
  32. testError = errors.New(gofakeit.Phrase())
  33. layout = "2006-01-02 15:04:05"
  34. correctReq = req{
  35. method: fiber.MethodPost,
  36. route: "/v1/places",
  37. body: &dto.AddPlaceRequest{
  38. Title: title,
  39. ParentID: &parentID,
  40. },
  41. contentType: fiber.MIMEApplicationJSON,
  42. }
  43. repoRes = models.Place{
  44. ID: placeID,
  45. Title: title,
  46. ParentID: sql.NullInt64{Int64: int64(parentID), Valid: true},
  47. CreatedAt: gofakeit.Date(),
  48. UpdatedAt: gofakeit.Date(),
  49. }
  50. expectedRes = dto.PlaceResponse{
  51. ID: placeID,
  52. ParentID: &parentID,
  53. Title: repoRes.Title,
  54. CreatedAt: repoRes.CreatedAt.Format(layout),
  55. UpdatedAt: repoRes.UpdatedAt.Format(layout),
  56. }
  57. )
  58. tests := []struct {
  59. name string
  60. req req
  61. resCode int
  62. resBody interface{}
  63. placeRepoMock func(mc *minimock.Controller) interfaces.PlaceRepository
  64. }{
  65. {
  66. name: "positive case",
  67. req: correctReq,
  68. resCode: fiber.StatusOK,
  69. resBody: expectedRes,
  70. placeRepoMock: func(mc *minimock.Controller) interfaces.PlaceRepository {
  71. mock := repoMocks.NewPlaceRepositoryMock(mc)
  72. mock.AddMock.Inspect(func(ctx context.Context, req models.AddPlaceRequest, tx *sql.Tx) {
  73. assert.Equal(mc, title, req.Title)
  74. assert.Equal(mc, int64(parentID), req.ParentID.Int64)
  75. }).Return(placeID, nil)
  76. mock.GetMock.Inspect(func(ctx context.Context, id int) {
  77. assert.Equal(mc, placeID, id)
  78. }).Return(&repoRes, nil)
  79. return mock
  80. },
  81. },
  82. {
  83. name: "negative case - body parse error",
  84. req: req{
  85. method: fiber.MethodPost,
  86. route: "/v1/places",
  87. },
  88. resCode: fiber.StatusBadRequest,
  89. placeRepoMock: func(mc *minimock.Controller) interfaces.PlaceRepository {
  90. return repoMocks.NewPlaceRepositoryMock(mc)
  91. },
  92. },
  93. {
  94. name: "negative case - request without title",
  95. req: req{
  96. method: fiber.MethodPost,
  97. route: "/v1/places",
  98. contentType: fiber.MIMEApplicationJSON,
  99. body: &dto.AddPlaceRequest{},
  100. },
  101. resCode: fiber.StatusBadRequest,
  102. resBody: []*dto.ValidateErrorResponse{
  103. {
  104. Field: "AddPlaceRequest.Title",
  105. Tag: "required",
  106. },
  107. },
  108. placeRepoMock: func(mc *minimock.Controller) interfaces.PlaceRepository {
  109. return repoMocks.NewPlaceRepositoryMock(mc)
  110. },
  111. },
  112. {
  113. name: "negative case - repository error (add place)",
  114. req: correctReq,
  115. resCode: fiber.StatusInternalServerError,
  116. placeRepoMock: func(mc *minimock.Controller) interfaces.PlaceRepository {
  117. mock := repoMocks.NewPlaceRepositoryMock(mc)
  118. mock.AddMock.Inspect(func(ctx context.Context, req models.AddPlaceRequest, tx *sql.Tx) {
  119. assert.Equal(mc, title, req.Title)
  120. assert.Equal(mc, int64(parentID), req.ParentID.Int64)
  121. }).Return(0, testError)
  122. return mock
  123. },
  124. },
  125. {
  126. name: "negative case - repository error (get place)",
  127. req: correctReq,
  128. resCode: fiber.StatusInternalServerError,
  129. placeRepoMock: func(mc *minimock.Controller) interfaces.PlaceRepository {
  130. mock := repoMocks.NewPlaceRepositoryMock(mc)
  131. mock.AddMock.Inspect(func(ctx context.Context, req models.AddPlaceRequest, tx *sql.Tx) {
  132. assert.Equal(mc, title, req.Title)
  133. assert.Equal(mc, int64(parentID), req.ParentID.Int64)
  134. }).Return(placeID, nil)
  135. mock.GetMock.Inspect(func(ctx context.Context, id int) {
  136. assert.Equal(mc, placeID, id)
  137. }).Return(nil, testError)
  138. return mock
  139. },
  140. },
  141. }
  142. for _, tt := range tests {
  143. t.Run(tt.name, func(t *testing.T) {
  144. fiberApp := fiber.New()
  145. serviceProvider := sp.InitMock(tt.placeRepoMock(mc))
  146. fiberApp.Post("/v1/places", AddPlaceHandler(serviceProvider))
  147. fiberReq := httptest.NewRequest(tt.req.method, tt.req.route, helpers.ConvertDataToIOReader(tt.req.body))
  148. fiberReq.Header.Add(fiber.HeaderContentType, tt.req.contentType)
  149. fiberRes, _ := fiberApp.Test(fiberReq, API.DefaultTestTimeOut)
  150. assert.Equal(t, tt.resCode, fiberRes.StatusCode)
  151. if tt.resBody != nil {
  152. assert.Equal(t, helpers.MarshalResponse(tt.resBody), helpers.ConvertBodyToString(fiberRes.Body))
  153. }
  154. })
  155. }
  156. }