update_user_test.go 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. package user
  2. import (
  3. "context"
  4. "database/sql"
  5. "net/http/httptest"
  6. "testing"
  7. "github.com/brianvoe/gofakeit/v6"
  8. "github.com/gofiber/fiber/v2"
  9. "github.com/gojuno/minimock/v3"
  10. "github.com/golang-jwt/jwt/v4"
  11. "github.com/stretchr/testify/assert"
  12. "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/user/mocks"
  13. "git.dmitriygnatenko.ru/dima/homethings/internal/dto"
  14. "git.dmitriygnatenko.ru/dima/homethings/internal/helpers/test"
  15. "git.dmitriygnatenko.ru/dima/homethings/internal/models"
  16. "git.dmitriygnatenko.ru/dima/homethings/internal/services/auth"
  17. )
  18. func TestUpdateUserHandler(t *testing.T) {
  19. t.Parallel()
  20. type req struct {
  21. method string
  22. route string
  23. contentType string
  24. body *dto.UpdateUserRequest
  25. }
  26. var (
  27. username = gofakeit.Username()
  28. password = gofakeit.Word()
  29. hash = gofakeit.Word()
  30. testError = gofakeit.Error()
  31. claims = jwt.MapClaims{
  32. auth.ClaimsKeyName: username,
  33. }
  34. user = models.User{
  35. ID: gofakeit.Uint64(),
  36. Username: username,
  37. Password: password,
  38. CreatedAt: gofakeit.Date(),
  39. UpdatedAt: gofakeit.Date(),
  40. }
  41. correctReq = req{
  42. method: fiber.MethodPut,
  43. route: "/v1/users/",
  44. body: &dto.UpdateUserRequest{
  45. Username: &username,
  46. Password: &password,
  47. },
  48. contentType: fiber.MIMEApplicationJSON,
  49. }
  50. )
  51. tests := []struct {
  52. name string
  53. req req
  54. resCode int
  55. resBody interface{}
  56. authService func(mc *minimock.Controller) AuthService
  57. userRepoMock func(mc *minimock.Controller) UserRepository
  58. }{
  59. {
  60. name: "positive case",
  61. req: correctReq,
  62. resCode: fiber.StatusOK,
  63. resBody: dto.EmptyResponse{},
  64. authService: func(mc *minimock.Controller) AuthService {
  65. mock := mocks.NewAuthServiceMock(mc)
  66. mock.GeneratePasswordHashMock.Inspect(func(p string) {
  67. assert.Equal(mc, password, p)
  68. }).Return(hash, nil)
  69. mock.GetClaimsMock.Return(claims)
  70. return mock
  71. },
  72. userRepoMock: func(mc *minimock.Controller) UserRepository {
  73. mock := mocks.NewUserRepositoryMock(mc)
  74. mock.GetMock.Inspect(func(ctx context.Context, u string) {
  75. assert.Equal(mc, username, u)
  76. }).Return(&user, nil)
  77. mock.UpdateMock.Inspect(func(ctx context.Context, req models.UpdateUserRequest) {
  78. assert.Equal(mc, hash, req.Password.String)
  79. assert.Equal(mc, username, req.Username.String)
  80. }).Return(nil)
  81. return mock
  82. },
  83. },
  84. {
  85. name: "negative case - bad request",
  86. req: req{
  87. method: fiber.MethodPut,
  88. route: "/v1/users/",
  89. body: &dto.UpdateUserRequest{},
  90. contentType: fiber.MIMEApplicationJSON,
  91. },
  92. resCode: fiber.StatusBadRequest,
  93. authService: func(mc *minimock.Controller) AuthService {
  94. return mocks.NewAuthServiceMock(mc)
  95. },
  96. userRepoMock: func(mc *minimock.Controller) UserRepository {
  97. return mocks.NewUserRepositoryMock(mc)
  98. },
  99. },
  100. {
  101. name: "negative case - body parse error",
  102. req: req{
  103. method: fiber.MethodPut,
  104. route: "/v1/users/",
  105. body: &dto.UpdateUserRequest{},
  106. },
  107. resCode: fiber.StatusBadRequest,
  108. authService: func(mc *minimock.Controller) AuthService {
  109. return mocks.NewAuthServiceMock(mc)
  110. },
  111. userRepoMock: func(mc *minimock.Controller) UserRepository {
  112. return mocks.NewUserRepositoryMock(mc)
  113. },
  114. },
  115. {
  116. name: "negative case - auth service error",
  117. req: correctReq,
  118. resCode: fiber.StatusInternalServerError,
  119. authService: func(mc *minimock.Controller) AuthService {
  120. mock := mocks.NewAuthServiceMock(mc)
  121. mock.GeneratePasswordHashMock.Inspect(func(p string) {
  122. assert.Equal(mc, password, p)
  123. }).Return("", testError)
  124. return mock
  125. },
  126. userRepoMock: func(mc *minimock.Controller) UserRepository {
  127. return mocks.NewUserRepositoryMock(mc)
  128. },
  129. },
  130. {
  131. name: "negative case - repository error - get user",
  132. req: correctReq,
  133. resCode: fiber.StatusInternalServerError,
  134. authService: func(mc *minimock.Controller) AuthService {
  135. mock := mocks.NewAuthServiceMock(mc)
  136. mock.GeneratePasswordHashMock.Inspect(func(p string) {
  137. assert.Equal(mc, password, p)
  138. }).Return(hash, nil)
  139. mock.GetClaimsMock.Return(claims)
  140. return mock
  141. },
  142. userRepoMock: func(mc *minimock.Controller) UserRepository {
  143. mock := mocks.NewUserRepositoryMock(mc)
  144. mock.GetMock.Inspect(func(ctx context.Context, u string) {
  145. assert.Equal(mc, username, u)
  146. }).Return(nil, testError)
  147. return mock
  148. },
  149. },
  150. {
  151. name: "negative case - repository error - update user",
  152. req: correctReq,
  153. resCode: fiber.StatusInternalServerError,
  154. authService: func(mc *minimock.Controller) AuthService {
  155. mock := mocks.NewAuthServiceMock(mc)
  156. mock.GeneratePasswordHashMock.Inspect(func(p string) {
  157. assert.Equal(mc, password, p)
  158. }).Return(hash, nil)
  159. mock.GetClaimsMock.Return(claims)
  160. return mock
  161. },
  162. userRepoMock: func(mc *minimock.Controller) UserRepository {
  163. mock := mocks.NewUserRepositoryMock(mc)
  164. mock.GetMock.Inspect(func(ctx context.Context, u string) {
  165. assert.Equal(mc, username, u)
  166. }).Return(&user, nil)
  167. mock.UpdateMock.Inspect(func(ctx context.Context, req models.UpdateUserRequest) {
  168. assert.Equal(mc, hash, req.Password.String)
  169. assert.Equal(mc, username, req.Username.String)
  170. }).Return(testError)
  171. return mock
  172. },
  173. },
  174. {
  175. name: "negative case - user not found",
  176. req: correctReq,
  177. resCode: fiber.StatusBadRequest,
  178. authService: func(mc *minimock.Controller) AuthService {
  179. mock := mocks.NewAuthServiceMock(mc)
  180. mock.GeneratePasswordHashMock.Inspect(func(p string) {
  181. assert.Equal(mc, password, p)
  182. }).Return(hash, nil)
  183. mock.GetClaimsMock.Return(claims)
  184. return mock
  185. },
  186. userRepoMock: func(mc *minimock.Controller) UserRepository {
  187. mock := mocks.NewUserRepositoryMock(mc)
  188. mock.GetMock.Inspect(func(ctx context.Context, u string) {
  189. assert.Equal(mc, username, u)
  190. }).Return(nil, sql.ErrNoRows)
  191. return mock
  192. },
  193. },
  194. }
  195. for _, tt := range tests {
  196. t.Run(tt.name, func(t *testing.T) {
  197. t.Parallel()
  198. mc := minimock.NewController(t)
  199. fiberApp := fiber.New()
  200. fiberApp.Put("/v1/users", UpdateUserHandler(tt.authService(mc), tt.userRepoMock(mc)))
  201. fiberReq := httptest.NewRequest(tt.req.method, tt.req.route, test.ConvertDataToIOReader(tt.req.body))
  202. fiberReq.Header.Add(fiber.HeaderContentType, tt.req.contentType)
  203. fiberRes, _ := fiberApp.Test(fiberReq, test.TestTimeout)
  204. assert.Equal(t, tt.resCode, fiberRes.StatusCode)
  205. if tt.resBody != nil {
  206. assert.Equal(t, test.MarshalResponse(tt.resBody), test.ConvertBodyToString(fiberRes.Body))
  207. }
  208. })
  209. }
  210. }