Jelajahi Sumber

Refactoring

Dima 4 bulan lalu
induk
melakukan
18bfe1032f
100 mengubah file dengan 16035 tambahan dan 2391 penghapusan
  1. 0 34
      .golangci.yml
  2. 4 1
      Makefile
  3. TEMPAT SAMPAH
      build/app/app
  4. 2 1
      cmd/app/main.go
  5. 4 2
      docs/docs.go
  6. 1 0
      docs/swagger.json
  7. 2 1
      docs/swagger.yaml
  8. 198 27
      go.mod
  9. 30 7
      internal/api/v1/auth/check_auth.go
  10. 27 27
      internal/api/v1/auth/check_auth_test.go
  11. 13 9
      internal/api/v1/auth/login.go
  12. 45 44
      internal/api/v1/auth/login_test.go
  13. 1004 0
      internal/api/v1/auth/mocks/auth_service_minimock.go
  14. 395 0
      internal/api/v1/auth/mocks/user_repository_minimock.go
  15. 46 10
      internal/api/v1/image/add_image.go
  16. 98 92
      internal/api/v1/image/add_image_test.go
  17. 11 7
      internal/api/v1/image/delete_place_image.go
  18. 42 37
      internal/api/v1/image/delete_place_image_test.go
  19. 11 7
      internal/api/v1/image/delete_thing_image.go
  20. 42 37
      internal/api/v1/image/delete_thing_image_test.go
  21. 9 6
      internal/api/v1/image/get_place_images.go
  22. 34 29
      internal/api/v1/image/get_place_images_test.go
  23. 7 5
      internal/api/v1/image/get_thing_images.go
  24. 20 18
      internal/api/v1/image/get_thing_images_test.go
  25. 264 51
      internal/api/v1/image/mocks/file_repository_minimock.go
  26. 525 84
      internal/api/v1/image/mocks/place_image_repository_minimock.go
  27. 525 84
      internal/api/v1/image/mocks/thing_image_repository_minimock.go
  28. 28 8
      internal/api/v1/notification/add_thing_notification.go
  29. 29 28
      internal/api/v1/notification/add_thing_notification_test.go
  30. 9 6
      internal/api/v1/notification/delete_thing_notification.go
  31. 22 21
      internal/api/v1/notification/delete_thing_notification_test.go
  32. 7 5
      internal/api/v1/notification/get_expired_thing_notifications.go
  33. 18 17
      internal/api/v1/notification/get_expired_thing_notifications_test.go
  34. 9 6
      internal/api/v1/notification/get_thing_notification.go
  35. 22 21
      internal/api/v1/notification/get_thing_notification_test.go
  36. 513 78
      internal/api/v1/notification/mocks/thing_notification_repository_minimock.go
  37. 11 9
      internal/api/v1/notification/update_thing_notification.go
  38. 32 31
      internal/api/v1/notification/update_thing_notification_test.go
  39. 61 7
      internal/api/v1/place/add_place.go
  40. 24 23
      internal/api/v1/place/add_place_test.go
  41. 29 22
      internal/api/v1/place/delete_place.go
  42. 251 251
      internal/api/v1/place/delete_place_test.go
  43. 7 6
      internal/api/v1/place/get_place.go
  44. 5 5
      internal/api/v1/place/get_place_nested.go
  45. 20 19
      internal/api/v1/place/get_place_nested_test.go
  46. 22 21
      internal/api/v1/place/get_place_test.go
  47. 5 5
      internal/api/v1/place/get_place_tree.go
  48. 18 17
      internal/api/v1/place/get_place_tree_test.go
  49. 5 5
      internal/api/v1/place/get_places.go
  50. 18 17
      internal/api/v1/place/get_places_test.go
  51. 364 0
      internal/api/v1/place/mocks/file_repository_minimock.go
  52. 756 0
      internal/api/v1/place/mocks/place_image_repository_minimock.go
  53. 525 84
      internal/api/v1/place/mocks/place_repository_minimock.go
  54. 422 0
      internal/api/v1/place/mocks/place_thing_repository_minimock.go
  55. 756 0
      internal/api/v1/place/mocks/thing_image_repository_minimock.go
  56. 422 0
      internal/api/v1/place/mocks/thing_notification_repository_minimock.go
  57. 756 0
      internal/api/v1/place/mocks/thing_repository_minimock.go
  58. 422 0
      internal/api/v1/place/mocks/thing_tag_repository_minimock.go
  59. 7 7
      internal/api/v1/place/update_place.go
  60. 26 25
      internal/api/v1/place/update_place_test.go
  61. 38 7
      internal/api/v1/tag/add_tag.go
  62. 26 25
      internal/api/v1/tag/add_tag_test.go
  63. 13 8
      internal/api/v1/tag/add_thing_tag.go
  64. 68 62
      internal/api/v1/tag/add_thing_tag_test.go
  65. 13 9
      internal/api/v1/tag/delete_tag.go
  66. 46 45
      internal/api/v1/tag/delete_tag_test.go
  67. 13 8
      internal/api/v1/tag/delete_thing_tag.go
  68. 68 62
      internal/api/v1/tag/delete_thing_tag_test.go
  69. 7 6
      internal/api/v1/tag/get_tag.go
  70. 22 21
      internal/api/v1/tag/get_tag_test.go
  71. 5 5
      internal/api/v1/tag/get_tags.go
  72. 18 17
      internal/api/v1/tag/get_tags_test.go
  73. 5 5
      internal/api/v1/tag/get_thing_tags.go
  74. 20 19
      internal/api/v1/tag/get_thing_tags_test.go
  75. 525 84
      internal/api/v1/tag/mocks/tag_repository_minimock.go
  76. 395 0
      internal/api/v1/tag/mocks/thing_repository_minimock.go
  77. 1143 0
      internal/api/v1/tag/mocks/thing_tag_repository_minimock.go
  78. 7 7
      internal/api/v1/tag/update_tag.go
  79. 28 27
      internal/api/v1/tag/update_tag_test.go
  80. 58 8
      internal/api/v1/thing/add_thing.go
  81. 51 50
      internal/api/v1/thing/add_thing_test.go
  82. 22 14
      internal/api/v1/thing/delete_thing.go
  83. 178 176
      internal/api/v1/thing/delete_thing_test.go
  84. 9 6
      internal/api/v1/thing/get_place_things.go
  85. 31 30
      internal/api/v1/thing/get_place_things_test.go
  86. 7 6
      internal/api/v1/thing/get_thing.go
  87. 22 21
      internal/api/v1/thing/get_thing_test.go
  88. 364 0
      internal/api/v1/thing/mocks/file_repository_minimock.go
  89. 555 74
      internal/api/v1/thing/mocks/place_thing_repository_minimock.go
  90. 756 0
      internal/api/v1/thing/mocks/thing_image_repository_minimock.go
  91. 422 0
      internal/api/v1/thing/mocks/thing_notification_repository_minimock.go
  92. 525 84
      internal/api/v1/thing/mocks/thing_repository_minimock.go
  93. 756 0
      internal/api/v1/thing/mocks/thing_tag_repository_minimock.go
  94. 5 5
      internal/api/v1/thing/search_thing.go
  95. 22 22
      internal/api/v1/thing/search_thing_test.go
  96. 15 12
      internal/api/v1/thing/update_thing.go
  97. 63 62
      internal/api/v1/thing/update_thing_test.go
  98. 29 6
      internal/api/v1/user/add_user.go
  99. 34 34
      internal/api/v1/user/add_user_test.go
  100. 671 0
      internal/api/v1/user/mocks/auth_service_minimock.go

+ 0 - 34
.golangci.yml

@@ -1,34 +0,0 @@
-# More info on config here: https://golangci-lint.run/usage/configuration/#config-file
-run:
-  skip-dirs:
-    - build
-    - frontend
-    - scripts
-
-output:
-  format: colored-line-number
-  print-issued-lines: true
-  print-linter-name: true
-
-linters-settings:
-  govet:
-    check-shadowing: true
-  revive:
-    min-confidence: 0
-  goconst:
-    min-len:         2
-    min-occurrences: 2
-
-linters:
-  disable-all: true
-  enable:
-    - govet
-    - ineffassign
-    - typecheck
-    - errcheck
-    - goconst
-    - goimports
-    - gosec
-    - revive
-    - gocritic
-    - prealloc

+ 4 - 1
Makefile

@@ -54,7 +54,7 @@ docker-up:
 docker-down:
 	docker compose down
 
-install-deps: install-lint install-goose install-swagger
+install-deps: install-lint install-goose install-minimock install-swagger
 
 install-lint:
 	go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
@@ -62,6 +62,9 @@ install-lint:
 install-goose:
 	go install github.com/pressly/goose/v3/cmd/goose@latest
 
+install-minimock:
+	go install github.com/gojuno/minimock/v3/cmd/minimock@latest
+
 install-swagger:
 	go install github.com/swaggo/swag/cmd/swag@latest
 

TEMPAT SAMPAH
build/app/app


+ 2 - 1
cmd/app/main.go

@@ -4,9 +4,10 @@ import (
 	"log"
 	"time"
 
+	_ "github.com/lib/pq"
+
 	"git.dmitriygnatenko.ru/dima/homethings/internal/fiber"
 	sp "git.dmitriygnatenko.ru/dima/homethings/internal/service_provider"
-	_ "github.com/lib/pq"
 )
 
 // @title 						Homethings API

+ 4 - 2
docs/docs.go

@@ -1,5 +1,4 @@
-// Package docs GENERATED BY SWAG; DO NOT EDIT
-// This file was generated by swaggo/swag
+// Package docs Code generated by swaggo/swag. DO NOT EDIT
 package docs
 
 import "github.com/swaggo/swag"
@@ -136,6 +135,7 @@ const docTemplate = `{
                         "items": {
                             "type": "file"
                         },
+                        "collectionFormat": "csv",
                         "description": "Files",
                         "name": "files",
                         "in": "formData",
@@ -2161,6 +2161,8 @@ var SwaggerInfo = &swag.Spec{
 	Description:      "",
 	InfoInstanceName: "swagger",
 	SwaggerTemplate:  docTemplate,
+	LeftDelim:        "{{",
+	RightDelim:       "}}",
 }
 
 func init() {

+ 1 - 0
docs/swagger.json

@@ -126,6 +126,7 @@
                         "items": {
                             "type": "file"
                         },
+                        "collectionFormat": "csv",
                         "description": "Files",
                         "name": "files",
                         "in": "formData",

+ 2 - 1
docs/swagger.yaml

@@ -349,7 +349,8 @@ paths:
         in: formData
         name: thing_id
         type: integer
-      - description: Files
+      - collectionFormat: csv
+        description: Files
         in: formData
         items:
           type: file

+ 198 - 27
go.mod

@@ -1,6 +1,6 @@
 module git.dmitriygnatenko.ru/dima/homethings
 
-go 1.19
+go 1.22.2
 
 require (
 	github.com/Masterminds/squirrel v1.5.3
@@ -10,60 +10,231 @@ require (
 	github.com/gofiber/fiber/v2 v2.42.0
 	github.com/gofiber/jwt/v3 v3.3.6
 	github.com/gofiber/swagger v0.1.7
-	github.com/gojuno/minimock/v3 v3.0.10
+	github.com/gojuno/minimock/v3 v3.3.13
 	github.com/golang-jwt/jwt/v4 v4.4.3
-	github.com/lib/pq v1.10.7
-	github.com/spf13/viper v1.15.0
-	github.com/stretchr/testify v1.8.1
-	github.com/swaggo/swag v1.8.7
-	golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e
+	github.com/lib/pq v1.10.9
+	github.com/spf13/viper v1.19.0
+	github.com/stretchr/testify v1.9.0
+	github.com/swaggo/swag v1.16.3
+	golang.org/x/crypto v0.25.0
 )
 
 require (
+	4d63.com/gocheckcompilerdirectives v1.2.1 // indirect
+	4d63.com/gochecknoglobals v0.2.1 // indirect
+	github.com/4meepo/tagalign v1.3.4 // indirect
+	github.com/Abirdcfly/dupword v0.0.14 // indirect
+	github.com/Antonboom/errname v0.1.13 // indirect
+	github.com/Antonboom/nilnil v0.1.9 // indirect
+	github.com/Antonboom/testifylint v1.4.3 // indirect
+	github.com/BurntSushi/toml v1.4.0 // indirect
+	github.com/Crocmagnon/fatcontext v0.4.0 // indirect
+	github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 // indirect
+	github.com/GaijinEntertainment/go-exhaustruct/v3 v3.3.0 // indirect
 	github.com/KyleBanks/depth v1.2.1 // indirect
+	github.com/Masterminds/semver/v3 v3.2.1 // indirect
+	github.com/OpenPeeDeeP/depguard/v2 v2.2.0 // indirect
+	github.com/alecthomas/go-check-sumtype v0.1.4 // indirect
+	github.com/alexkohler/nakedret/v2 v2.0.4 // indirect
+	github.com/alexkohler/prealloc v1.0.0 // indirect
+	github.com/alingse/asasalint v0.0.11 // indirect
 	github.com/andybalholm/brotli v1.0.4 // indirect
-	github.com/davecgh/go-spew v1.1.1 // indirect
-	github.com/fsnotify/fsnotify v1.6.0 // indirect
-	github.com/go-openapi/jsonpointer v0.19.5 // indirect
-	github.com/go-openapi/jsonreference v0.20.0 // indirect
-	github.com/go-openapi/spec v0.20.7 // indirect
-	github.com/go-openapi/swag v0.22.3 // indirect
+	github.com/ashanbrown/forbidigo v1.6.0 // indirect
+	github.com/ashanbrown/makezero v1.1.1 // indirect
+	github.com/beorn7/perks v1.0.1 // indirect
+	github.com/bkielbasa/cyclop v1.2.1 // indirect
+	github.com/blizzy78/varnamelen v0.8.0 // indirect
+	github.com/bombsimon/wsl/v4 v4.4.1 // indirect
+	github.com/breml/bidichk v0.2.7 // indirect
+	github.com/breml/errchkjson v0.3.6 // indirect
+	github.com/butuzov/ireturn v0.3.0 // indirect
+	github.com/butuzov/mirror v1.2.0 // indirect
+	github.com/catenacyber/perfsprint v0.7.1 // indirect
+	github.com/ccojocar/zxcvbn-go v1.0.2 // indirect
+	github.com/cespare/xxhash/v2 v2.3.0 // indirect
+	github.com/charithe/durationcheck v0.0.10 // indirect
+	github.com/chavacava/garif v0.1.0 // indirect
+	github.com/ckaznocha/intrange v0.1.2 // indirect
+	github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
+	github.com/curioswitch/go-reassign v0.2.0 // indirect
+	github.com/daixiang0/gci v0.13.4 // indirect
+	github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
+	github.com/denis-tingaikin/go-header v0.5.0 // indirect
+	github.com/ettle/strcase v0.2.0 // indirect
+	github.com/fatih/color v1.17.0 // indirect
+	github.com/fatih/structtag v1.2.0 // indirect
+	github.com/firefart/nonamedreturns v1.0.5 // indirect
+	github.com/fsnotify/fsnotify v1.7.0 // indirect
+	github.com/fzipp/gocyclo v0.6.0 // indirect
+	github.com/ghostiam/protogetter v0.3.6 // indirect
+	github.com/go-critic/go-critic v0.11.4 // indirect
+	github.com/go-openapi/jsonpointer v0.21.0 // indirect
+	github.com/go-openapi/jsonreference v0.21.0 // indirect
+	github.com/go-openapi/spec v0.21.0 // indirect
+	github.com/go-openapi/swag v0.23.0 // indirect
 	github.com/go-playground/locales v0.14.0 // indirect
 	github.com/go-playground/universal-translator v0.18.0 // indirect
-	github.com/google/uuid v1.3.0 // indirect
+	github.com/go-toolsmith/astcast v1.1.0 // indirect
+	github.com/go-toolsmith/astcopy v1.1.0 // indirect
+	github.com/go-toolsmith/astequal v1.2.0 // indirect
+	github.com/go-toolsmith/astfmt v1.1.0 // indirect
+	github.com/go-toolsmith/astp v1.1.0 // indirect
+	github.com/go-toolsmith/strparse v1.1.0 // indirect
+	github.com/go-toolsmith/typep v1.1.0 // indirect
+	github.com/go-viper/mapstructure/v2 v2.0.0 // indirect
+	github.com/go-xmlfmt/xmlfmt v1.1.2 // indirect
+	github.com/gobwas/glob v0.2.3 // indirect
+	github.com/gofrs/flock v0.12.1 // indirect
+	github.com/golang/protobuf v1.5.4 // indirect
+	github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a // indirect
+	github.com/golangci/gofmt v0.0.0-20240724082148-399ed8a42d42 // indirect
+	github.com/golangci/golangci-lint v1.59.1 // indirect
+	github.com/golangci/misspell v0.6.0 // indirect
+	github.com/golangci/modinfo v0.3.4 // indirect
+	github.com/golangci/plugin-module-register v0.1.1 // indirect
+	github.com/golangci/revgrep v0.5.3 // indirect
+	github.com/golangci/unconvert v0.0.0-20240309020433-c5143eacb3ed // indirect
+	github.com/google/go-cmp v0.6.0 // indirect
+	github.com/google/uuid v1.6.0 // indirect
+	github.com/gordonklaus/ineffassign v0.1.0 // indirect
+	github.com/gostaticanalysis/analysisutil v0.7.1 // indirect
+	github.com/gostaticanalysis/comment v1.4.2 // indirect
+	github.com/gostaticanalysis/forcetypeassert v0.1.0 // indirect
+	github.com/gostaticanalysis/nilerr v0.1.1 // indirect
+	github.com/hashicorp/go-version v1.7.0 // indirect
 	github.com/hashicorp/hcl v1.0.0 // indirect
+	github.com/hexdigest/gowrap v1.3.10 // indirect
+	github.com/hexops/gotextdiff v1.0.3 // indirect
+	github.com/inconshreveable/mousetrap v1.1.0 // indirect
+	github.com/jgautheron/goconst v1.7.1 // indirect
+	github.com/jingyugao/rowserrcheck v1.1.1 // indirect
+	github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af // indirect
+	github.com/jjti/go-spancheck v0.6.2 // indirect
 	github.com/josharian/intern v1.0.0 // indirect
-	github.com/klauspost/compress v1.15.12 // indirect
+	github.com/julz/importas v0.1.0 // indirect
+	github.com/karamaru-alpha/copyloopvar v1.1.0 // indirect
+	github.com/kisielk/errcheck v1.7.0 // indirect
+	github.com/kkHAIKE/contextcheck v1.1.5 // indirect
+	github.com/klauspost/compress v1.17.9 // indirect
+	github.com/kulti/thelper v0.6.3 // indirect
+	github.com/kunwardeep/paralleltest v1.0.10 // indirect
+	github.com/kyoh86/exportloopref v0.1.11 // indirect
 	github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect
 	github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect
+	github.com/lasiar/canonicalheader v1.1.1 // indirect
+	github.com/ldez/gomoddirectives v0.2.4 // indirect
+	github.com/ldez/tagliatelle v0.5.0 // indirect
 	github.com/leodido/go-urn v1.2.1 // indirect
+	github.com/leonklingele/grouper v1.1.2 // indirect
+	github.com/lufeee/execinquery v1.2.1 // indirect
+	github.com/macabu/inamedparam v0.1.3 // indirect
 	github.com/magiconair/properties v1.8.7 // indirect
 	github.com/mailru/easyjson v0.7.7 // indirect
+	github.com/maratori/testableexamples v1.0.0 // indirect
+	github.com/maratori/testpackage v1.1.1 // indirect
+	github.com/matoous/godox v0.0.0-20240105082147-c5b5e0e7c0c0 // indirect
 	github.com/mattn/go-colorable v0.1.13 // indirect
-	github.com/mattn/go-isatty v0.0.17 // indirect
-	github.com/mattn/go-runewidth v0.0.14 // indirect
+	github.com/mattn/go-isatty v0.0.20 // indirect
+	github.com/mattn/go-runewidth v0.0.16 // indirect
+	github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
+	github.com/mgechev/revive v1.3.9 // indirect
+	github.com/mitchellh/go-homedir v1.1.0 // indirect
 	github.com/mitchellh/mapstructure v1.5.0 // indirect
-	github.com/pelletier/go-toml/v2 v2.0.6 // indirect
+	github.com/moricho/tparallel v0.3.2 // indirect
+	github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
+	github.com/nakabonne/nestif v0.3.1 // indirect
+	github.com/nishanths/exhaustive v0.12.0 // indirect
+	github.com/nishanths/predeclared v0.2.2 // indirect
+	github.com/nunnatsa/ginkgolinter v0.16.2 // indirect
+	github.com/olekukonko/tablewriter v0.0.5 // indirect
+	github.com/pelletier/go-toml/v2 v2.2.2 // indirect
 	github.com/philhofer/fwd v1.1.1 // indirect
-	github.com/pmezard/go-difflib v1.0.0 // indirect
-	github.com/rivo/uniseg v0.4.2 // indirect
+	github.com/pkg/errors v0.9.1 // indirect
+	github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
+	github.com/polyfloyd/go-errorlint v1.5.2 // indirect
+	github.com/prometheus/client_golang v1.19.1 // indirect
+	github.com/prometheus/client_model v0.6.1 // indirect
+	github.com/prometheus/common v0.55.0 // indirect
+	github.com/prometheus/procfs v0.15.1 // indirect
+	github.com/quasilyte/go-ruleguard v0.4.2 // indirect
+	github.com/quasilyte/go-ruleguard/dsl v0.3.22 // indirect
+	github.com/quasilyte/gogrep v0.5.0 // indirect
+	github.com/quasilyte/regex/syntax v0.0.0-20210819130434-b3f0c404a727 // indirect
+	github.com/quasilyte/stdinfo v0.0.0-20220114132959-f7386bf02567 // indirect
+	github.com/rivo/uniseg v0.4.7 // indirect
+	github.com/rogpeppe/go-internal v1.12.0 // indirect
+	github.com/russross/blackfriday/v2 v2.1.0 // indirect
+	github.com/ryancurrah/gomodguard v1.3.3 // indirect
+	github.com/ryanrolds/sqlclosecheck v0.5.1 // indirect
+	github.com/sagikazarmark/locafero v0.6.0 // indirect
+	github.com/sagikazarmark/slog-shim v0.1.0 // indirect
+	github.com/sanposhiho/wastedassign/v2 v2.0.7 // indirect
+	github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 // indirect
+	github.com/sashamelentyev/interfacebloat v1.1.0 // indirect
+	github.com/sashamelentyev/usestdlibvars v1.27.0 // indirect
 	github.com/savsgio/dictpool v0.0.0-20221023140959-7bf2e61cea94 // indirect
 	github.com/savsgio/gotils v0.0.0-20220530130905-52f3993e8d6d // indirect
-	github.com/spf13/afero v1.9.3 // indirect
-	github.com/spf13/cast v1.5.0 // indirect
+	github.com/securego/gosec/v2 v2.20.1-0.20240525090044-5f0084eb01a9 // indirect
+	github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c // indirect
+	github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
+	github.com/sirupsen/logrus v1.9.3 // indirect
+	github.com/sivchari/containedctx v1.0.3 // indirect
+	github.com/sivchari/tenv v1.10.0 // indirect
+	github.com/sonatard/noctx v0.0.2 // indirect
+	github.com/sourcegraph/conc v0.3.0 // indirect
+	github.com/sourcegraph/go-diff v0.7.0 // indirect
+	github.com/spf13/afero v1.11.0 // indirect
+	github.com/spf13/cast v1.6.0 // indirect
+	github.com/spf13/cobra v1.8.1 // indirect
 	github.com/spf13/jwalterweatherman v1.1.0 // indirect
 	github.com/spf13/pflag v1.0.5 // indirect
-	github.com/subosito/gotenv v1.4.2 // indirect
+	github.com/ssgreg/nlreturn/v2 v2.2.1 // indirect
+	github.com/stbenjam/no-sprintf-host-port v0.1.1 // indirect
+	github.com/stretchr/objx v0.5.2 // indirect
+	github.com/subosito/gotenv v1.6.0 // indirect
 	github.com/swaggo/files v0.0.0-20220728132757-551d4a08d97a // indirect
+	github.com/t-yuki/gocover-cobertura v0.0.0-20180217150009-aaee18c8195c // indirect
+	github.com/tdakkota/asciicheck v0.2.0 // indirect
+	github.com/tetafro/godot v1.4.16 // indirect
+	github.com/timakin/bodyclose v0.0.0-20240125160201-f835fa56326a // indirect
+	github.com/timonwong/loggercheck v0.9.4 // indirect
 	github.com/tinylib/msgp v1.1.6 // indirect
+	github.com/tomarrell/wrapcheck/v2 v2.8.3 // indirect
+	github.com/tommy-muehle/go-mnd/v2 v2.5.1 // indirect
+	github.com/ultraware/funlen v0.1.0 // indirect
+	github.com/ultraware/whitespace v0.1.1 // indirect
+	github.com/urfave/cli/v2 v2.27.3 // indirect
+	github.com/uudashr/gocognit v1.1.3 // indirect
 	github.com/valyala/bytebufferpool v1.0.0 // indirect
 	github.com/valyala/fasthttp v1.44.0 // indirect
 	github.com/valyala/tcplisten v1.0.0 // indirect
+	github.com/xen0n/gosmopolitan v1.2.2 // indirect
+	github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
+	github.com/yagipy/maintidx v1.0.0 // indirect
+	github.com/yeya24/promlinter v0.3.0 // indirect
+	github.com/ykadowak/zerologlint v0.1.5 // indirect
+	gitlab.com/bosi/decorder v0.4.2 // indirect
+	go-simpler.org/musttag v0.12.2 // indirect
+	go-simpler.org/sloglint v0.7.2 // indirect
+	go.uber.org/atomic v1.11.0 // indirect
+	go.uber.org/automaxprocs v1.5.3 // indirect
+	go.uber.org/multierr v1.11.0 // indirect
+	go.uber.org/zap v1.27.0 // indirect
+	golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
+	golang.org/x/exp/typeparams v0.0.0-20240719175910-8a7402abbf56 // indirect
 	golang.org/x/image v0.11.0 // indirect
-	golang.org/x/net v0.6.0 // indirect
-	golang.org/x/sys v0.5.0 // indirect
-	golang.org/x/text v0.12.0 // indirect
-	golang.org/x/tools v0.6.0 // indirect
+	golang.org/x/mod v0.19.0 // indirect
+	golang.org/x/net v0.27.0 // indirect
+	golang.org/x/sync v0.7.0 // indirect
+	golang.org/x/sys v0.22.0 // indirect
+	golang.org/x/text v0.16.0 // indirect
+	golang.org/x/tools v0.23.0 // indirect
+	google.golang.org/protobuf v1.34.2 // indirect
 	gopkg.in/ini.v1 v1.67.0 // indirect
+	gopkg.in/yaml.v2 v2.4.0 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
+	honnef.co/go/tools v0.4.7 // indirect
+	mvdan.cc/gofumpt v0.6.0 // indirect
+	mvdan.cc/unparam v0.0.0-20240528143540-8a5130ca722f // indirect
+	sigs.k8s.io/yaml v1.4.0 // indirect
 )

+ 30 - 7
internal/api/v1/auth/check_auth.go

@@ -1,11 +1,31 @@
 package auth
 
+//go:generate mkdir -p mocks
+//go:generate rm -rf ./mocks/*_minimock.go
+//go:generate minimock -i AuthService,UserRepository -o ./mocks/ -s "_minimock.go"
+
 import (
+	"context"
 	"database/sql"
+	"errors"
 
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/mappers"
 	"github.com/gofiber/fiber/v2"
+	"github.com/golang-jwt/jwt/v4"
+
+	"git.dmitriygnatenko.ru/dima/homethings/internal/mappers"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
+)
+
+type (
+	AuthService interface {
+		GetClaims(fctx *fiber.Ctx) jwt.MapClaims
+		IsCorrectPassword(password string, hash string) bool
+		GenerateToken(user models.User) (string, error)
+	}
+
+	UserRepository interface {
+		Get(ctx context.Context, username string) (*models.User, error)
+	}
 )
 
 // @Router 		/api/v1/auth/check [get]
@@ -16,20 +36,23 @@ import (
 // @Tags  		Auth
 // @Accept      json
 // @Produce     json
-func CheckAuthHandler(sp interfaces.ServiceProvider) fiber.Handler {
+func CheckAuthHandler(
+	authService AuthService,
+	userRepository UserRepository,
+) fiber.Handler {
 	return func(fctx *fiber.Ctx) error {
 		ctx := fctx.Context()
-		claims := sp.GetAuthService().GetClaims(fctx)
+		claims := authService.GetClaims(fctx)
 
-		user, err := sp.GetUserRepository().Get(ctx, claims["name"].(string))
+		user, err := userRepository.Get(ctx, claims["name"].(string))
 		if err != nil {
-			if err == sql.ErrNoRows {
+			if errors.Is(err, sql.ErrNoRows) {
 				return fiber.NewError(fiber.StatusForbidden, "")
 			}
 
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
-		return fctx.JSON(mappers.ConvertToUserResponseDTO(*user))
+		return fctx.JSON(mappers.ToUserResponse(*user))
 	}
 }

+ 27 - 27
internal/api/v1/auth/check_auth_test.go

@@ -7,22 +7,22 @@ import (
 	"net/http/httptest"
 	"testing"
 
-	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
-	repoMocks "git.dmitriygnatenko.ru/dima/homethings/internal/repositories/mocks"
-	sp "git.dmitriygnatenko.ru/dima/homethings/internal/service_provider"
-	authMocks "git.dmitriygnatenko.ru/dima/homethings/internal/services/auth/mocks"
 	"github.com/brianvoe/gofakeit/v6"
 	"github.com/gofiber/fiber/v2"
 	"github.com/gojuno/minimock/v3"
 	"github.com/golang-jwt/jwt/v4"
 	"github.com/stretchr/testify/assert"
+
+	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/auth/mocks"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
 )
 
-func Test_CheckAuthHandler(t *testing.T) {
+func TestCheckAuthHandler(t *testing.T) {
+	t.Parallel()
+
 	type req struct {
 		method      string
 		route       string
@@ -30,7 +30,6 @@ func Test_CheckAuthHandler(t *testing.T) {
 	}
 
 	var (
-		mc        = minimock.NewController(t)
 		username  = gofakeit.Username()
 		testError = errors.New(gofakeit.Phrase())
 
@@ -56,16 +55,16 @@ func Test_CheckAuthHandler(t *testing.T) {
 		req             req
 		resCode         int
 		resBody         interface{}
-		userRepoMock    func(mc *minimock.Controller) interfaces.UserRepository
-		authServiceMock func(mc *minimock.Controller) interfaces.Auth
+		userRepoMock    func(mc *minimock.Controller) UserRepository
+		authServiceMock func(mc *minimock.Controller) AuthService
 	}{
 		{
 			name:    "positive case",
 			req:     correctReq,
 			resCode: fiber.StatusOK,
 			resBody: expectedRes,
-			userRepoMock: func(mc *minimock.Controller) interfaces.UserRepository {
-				mock := repoMocks.NewUserRepositoryMock(mc)
+			userRepoMock: func(mc *minimock.Controller) UserRepository {
+				mock := mocks.NewUserRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, reqUsername string) {
 					assert.Equal(mc, username, reqUsername)
@@ -73,8 +72,8 @@ func Test_CheckAuthHandler(t *testing.T) {
 
 				return mock
 			},
-			authServiceMock: func(mc *minimock.Controller) interfaces.Auth {
-				mock := authMocks.NewAuthMock(mc)
+			authServiceMock: func(mc *minimock.Controller) AuthService {
+				mock := mocks.NewAuthServiceMock(mc)
 				mock.GetClaimsMock.Return(claims)
 				return mock
 			},
@@ -83,8 +82,8 @@ func Test_CheckAuthHandler(t *testing.T) {
 			name:    "negative case - user not found",
 			req:     correctReq,
 			resCode: fiber.StatusForbidden,
-			userRepoMock: func(mc *minimock.Controller) interfaces.UserRepository {
-				mock := repoMocks.NewUserRepositoryMock(mc)
+			userRepoMock: func(mc *minimock.Controller) UserRepository {
+				mock := mocks.NewUserRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, reqUsername string) {
 					assert.Equal(mc, username, reqUsername)
@@ -92,8 +91,8 @@ func Test_CheckAuthHandler(t *testing.T) {
 
 				return mock
 			},
-			authServiceMock: func(mc *minimock.Controller) interfaces.Auth {
-				mock := authMocks.NewAuthMock(mc)
+			authServiceMock: func(mc *minimock.Controller) AuthService {
+				mock := mocks.NewAuthServiceMock(mc)
 				mock.GetClaimsMock.Return(claims)
 				return mock
 			},
@@ -102,8 +101,8 @@ func Test_CheckAuthHandler(t *testing.T) {
 			name:    "negative case - repository error",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			userRepoMock: func(mc *minimock.Controller) interfaces.UserRepository {
-				mock := repoMocks.NewUserRepositoryMock(mc)
+			userRepoMock: func(mc *minimock.Controller) UserRepository {
+				mock := mocks.NewUserRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, reqUsername string) {
 					assert.Equal(mc, username, reqUsername)
@@ -111,8 +110,8 @@ func Test_CheckAuthHandler(t *testing.T) {
 
 				return mock
 			},
-			authServiceMock: func(mc *minimock.Controller) interfaces.Auth {
-				mock := authMocks.NewAuthMock(mc)
+			authServiceMock: func(mc *minimock.Controller) AuthService {
+				mock := mocks.NewAuthServiceMock(mc)
 				mock.GetClaimsMock.Return(claims)
 				return mock
 			},
@@ -121,10 +120,11 @@ func Test_CheckAuthHandler(t *testing.T) {
 
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			fiberApp := fiber.New()
-			serviceProvider := sp.InitMock(tt.userRepoMock(mc), tt.authServiceMock(mc))
+			t.Parallel()
 
-			fiberApp.Get("/v1/auth/check", CheckAuthHandler(serviceProvider))
+			mc := minimock.NewController(t)
+			fiberApp := fiber.New()
+			fiberApp.Get("/v1/auth/check", CheckAuthHandler(tt.authServiceMock(mc), tt.userRepoMock(mc)))
 
 			fiberRes, _ := fiberApp.Test(httptest.NewRequest(tt.req.method, tt.req.route, nil), API.DefaultTestTimeOut)
 			assert.Equal(t, tt.resCode, fiberRes.StatusCode)

+ 13 - 9
internal/api/v1/auth/login.go

@@ -2,13 +2,14 @@ package auth
 
 import (
 	"database/sql"
+	"errors"
+
+	"github.com/go-playground/validator/v10"
+	"github.com/gofiber/fiber/v2"
 
 	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/factory"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/mappers"
-	"github.com/go-playground/validator/v10"
-	"github.com/gofiber/fiber/v2"
 )
 
 // @Router 		/api/v1/auth/login [post]
@@ -21,7 +22,10 @@ import (
 // @Tags  		Auth
 // @Accept      json
 // @Produce     json
-func LoginHandler(sp interfaces.ServiceProvider) fiber.Handler {
+func LoginHandler(
+	authService AuthService,
+	userRepository UserRepository,
+) fiber.Handler {
 	return func(fctx *fiber.Ctx) error {
 		ctx := fctx.Context()
 		req := dto.LoginRequest{}
@@ -34,24 +38,24 @@ func LoginHandler(sp interfaces.ServiceProvider) fiber.Handler {
 			return fctx.Status(fiber.StatusBadRequest).JSON(factory.CreateValidateErrorResponse(err))
 		}
 
-		user, err := sp.GetUserRepository().Get(ctx, req.Username)
+		user, err := userRepository.Get(ctx, req.Username)
 		if err != nil {
-			if err == sql.ErrNoRows {
+			if errors.Is(err, sql.ErrNoRows) {
 				return fiber.NewError(fiber.StatusForbidden, "")
 			}
 
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
-		if !sp.GetAuthService().IsCorrectPassword(req.Password, user.Password) {
+		if !authService.IsCorrectPassword(req.Password, user.Password) {
 			return fiber.NewError(fiber.StatusForbidden, "")
 		}
 
-		token, err := sp.GetAuthService().GenerateToken(*user)
+		token, err := authService.GenerateToken(*user)
 		if err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
-		return fctx.JSON(mappers.ConvertToLoginResponseDTO(token))
+		return fctx.JSON(mappers.ToLoginResponse(token))
 	}
 }

+ 45 - 44
internal/api/v1/auth/login_test.go

@@ -7,21 +7,21 @@ import (
 	"net/http/httptest"
 	"testing"
 
-	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
-	repoMocks "git.dmitriygnatenko.ru/dima/homethings/internal/repositories/mocks"
-	sp "git.dmitriygnatenko.ru/dima/homethings/internal/service_provider"
-	authMocks "git.dmitriygnatenko.ru/dima/homethings/internal/services/auth/mocks"
 	"github.com/brianvoe/gofakeit/v6"
 	"github.com/gofiber/fiber/v2"
 	"github.com/gojuno/minimock/v3"
 	"github.com/stretchr/testify/assert"
+
+	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/auth/mocks"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
 )
 
-func Test_LoginHandler(t *testing.T) {
+func TestLoginHandler(t *testing.T) {
+	t.Parallel()
+
 	type req struct {
 		method      string
 		route       string
@@ -30,7 +30,6 @@ func Test_LoginHandler(t *testing.T) {
 	}
 
 	var (
-		mc           = minimock.NewController(t)
 		id           = gofakeit.Number(1, 1000)
 		username     = gofakeit.Username()
 		password     = gofakeit.Word()
@@ -60,16 +59,16 @@ func Test_LoginHandler(t *testing.T) {
 		req             req
 		resCode         int
 		resBody         interface{}
-		userRepoMock    func(mc *minimock.Controller) interfaces.UserRepository
-		authServiceMock func(mc *minimock.Controller) interfaces.Auth
+		userRepoMock    func(mc *minimock.Controller) UserRepository
+		authServiceMock func(mc *minimock.Controller) AuthService
 	}{
 		{
 			name:    "positive case",
 			req:     correctReq,
 			resCode: fiber.StatusOK,
 			resBody: dto.LoginResponse{Token: token},
-			userRepoMock: func(mc *minimock.Controller) interfaces.UserRepository {
-				mock := repoMocks.NewUserRepositoryMock(mc)
+			userRepoMock: func(mc *minimock.Controller) UserRepository {
+				mock := mocks.NewUserRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, reqUsername string) {
 					assert.Equal(mc, username, reqUsername)
@@ -77,10 +76,10 @@ func Test_LoginHandler(t *testing.T) {
 
 				return mock
 			},
-			authServiceMock: func(mc *minimock.Controller) interfaces.Auth {
-				mock := authMocks.NewAuthMock(mc)
+			authServiceMock: func(mc *minimock.Controller) AuthService {
+				mock := mocks.NewAuthServiceMock(mc)
 
-				mock.IsCorrectPasswordMock.Expect(password, passwordHash).Return(true)
+				mock.IsCorrectPasswordMock.Return(true)
 				mock.GenerateTokenMock.Expect(user).Return(token, nil)
 
 				return mock
@@ -93,11 +92,11 @@ func Test_LoginHandler(t *testing.T) {
 				route:  "/v1/auth/login",
 			},
 			resCode: fiber.StatusBadRequest,
-			userRepoMock: func(mc *minimock.Controller) interfaces.UserRepository {
-				return repoMocks.NewUserRepositoryMock(mc)
+			userRepoMock: func(mc *minimock.Controller) UserRepository {
+				return mocks.NewUserRepositoryMock(mc)
 			},
-			authServiceMock: func(mc *minimock.Controller) interfaces.Auth {
-				return authMocks.NewAuthMock(mc)
+			authServiceMock: func(mc *minimock.Controller) AuthService {
+				return mocks.NewAuthServiceMock(mc)
 			},
 		},
 		{
@@ -111,19 +110,19 @@ func Test_LoginHandler(t *testing.T) {
 				contentType: fiber.MIMEApplicationJSON,
 			},
 			resCode: fiber.StatusBadRequest,
-			userRepoMock: func(mc *minimock.Controller) interfaces.UserRepository {
-				return repoMocks.NewUserRepositoryMock(mc)
+			userRepoMock: func(mc *minimock.Controller) UserRepository {
+				return mocks.NewUserRepositoryMock(mc)
 			},
-			authServiceMock: func(mc *minimock.Controller) interfaces.Auth {
-				return authMocks.NewAuthMock(mc)
+			authServiceMock: func(mc *minimock.Controller) AuthService {
+				return mocks.NewAuthServiceMock(mc)
 			},
 		},
 		{
 			name:    "negative case - generate token error",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			userRepoMock: func(mc *minimock.Controller) interfaces.UserRepository {
-				mock := repoMocks.NewUserRepositoryMock(mc)
+			userRepoMock: func(mc *minimock.Controller) UserRepository {
+				mock := mocks.NewUserRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, reqUsername string) {
 					assert.Equal(mc, username, reqUsername)
@@ -131,8 +130,8 @@ func Test_LoginHandler(t *testing.T) {
 
 				return mock
 			},
-			authServiceMock: func(mc *minimock.Controller) interfaces.Auth {
-				mock := authMocks.NewAuthMock(mc)
+			authServiceMock: func(mc *minimock.Controller) AuthService {
+				mock := mocks.NewAuthServiceMock(mc)
 
 				mock.IsCorrectPasswordMock.Expect(password, passwordHash).Return(true)
 				mock.GenerateTokenMock.Expect(user).Return("", testError)
@@ -144,8 +143,8 @@ func Test_LoginHandler(t *testing.T) {
 			name:    "negative case - incorrect password",
 			req:     correctReq,
 			resCode: fiber.StatusForbidden,
-			userRepoMock: func(mc *minimock.Controller) interfaces.UserRepository {
-				mock := repoMocks.NewUserRepositoryMock(mc)
+			userRepoMock: func(mc *minimock.Controller) UserRepository {
+				mock := mocks.NewUserRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, reqUsername string) {
 					assert.Equal(mc, username, reqUsername)
@@ -153,8 +152,9 @@ func Test_LoginHandler(t *testing.T) {
 
 				return mock
 			},
-			authServiceMock: func(mc *minimock.Controller) interfaces.Auth {
-				mock := authMocks.NewAuthMock(mc)
+			authServiceMock: func(mc *minimock.Controller) AuthService {
+				mock := mocks.NewAuthServiceMock(mc)
+
 				mock.IsCorrectPasswordMock.Expect(password, passwordHash).Return(false)
 				return mock
 			},
@@ -163,8 +163,8 @@ func Test_LoginHandler(t *testing.T) {
 			name:    "negative case - repository error (get user)",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			userRepoMock: func(mc *minimock.Controller) interfaces.UserRepository {
-				mock := repoMocks.NewUserRepositoryMock(mc)
+			userRepoMock: func(mc *minimock.Controller) UserRepository {
+				mock := mocks.NewUserRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, reqUsername string) {
 					assert.Equal(mc, username, reqUsername)
@@ -172,16 +172,16 @@ func Test_LoginHandler(t *testing.T) {
 
 				return mock
 			},
-			authServiceMock: func(mc *minimock.Controller) interfaces.Auth {
-				return authMocks.NewAuthMock(mc)
+			authServiceMock: func(mc *minimock.Controller) AuthService {
+				return mocks.NewAuthServiceMock(mc)
 			},
 		},
 		{
 			name:    "negative case - user not found",
 			req:     correctReq,
 			resCode: fiber.StatusForbidden,
-			userRepoMock: func(mc *minimock.Controller) interfaces.UserRepository {
-				mock := repoMocks.NewUserRepositoryMock(mc)
+			userRepoMock: func(mc *minimock.Controller) UserRepository {
+				mock := mocks.NewUserRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, reqUsername string) {
 					assert.Equal(mc, username, reqUsername)
@@ -189,18 +189,19 @@ func Test_LoginHandler(t *testing.T) {
 
 				return mock
 			},
-			authServiceMock: func(mc *minimock.Controller) interfaces.Auth {
-				return authMocks.NewAuthMock(mc)
+			authServiceMock: func(mc *minimock.Controller) AuthService {
+				return mocks.NewAuthServiceMock(mc)
 			},
 		},
 	}
 
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			fiberApp := fiber.New()
-			serviceProvider := sp.InitMock(tt.userRepoMock(mc), tt.authServiceMock(mc))
+			t.Parallel()
 
-			fiberApp.Post("/v1/auth/login", LoginHandler(serviceProvider))
+			mc := minimock.NewController(t)
+			fiberApp := fiber.New()
+			fiberApp.Post("/v1/auth/login", LoginHandler(tt.authServiceMock(mc), tt.userRepoMock(mc)))
 
 			fiberReq := httptest.NewRequest(tt.req.method, tt.req.route, helpers.ConvertDataToIOReader(tt.req.body))
 			fiberReq.Header.Add(fiber.HeaderContentType, tt.req.contentType)

+ 1004 - 0
internal/api/v1/auth/mocks/auth_service_minimock.go

@@ -0,0 +1,1004 @@
+// Code generated by http://github.com/gojuno/minimock (v3.3.13). DO NOT EDIT.
+
+package mocks
+
+//go:generate minimock -i git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/auth.AuthService -o auth_service_minimock.go -n AuthServiceMock -p mocks
+
+import (
+	"sync"
+	mm_atomic "sync/atomic"
+	mm_time "time"
+
+	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
+	"github.com/gofiber/fiber/v2"
+	"github.com/gojuno/minimock/v3"
+	"github.com/golang-jwt/jwt/v4"
+)
+
+// AuthServiceMock implements auth.AuthService
+type AuthServiceMock struct {
+	t          minimock.Tester
+	finishOnce sync.Once
+
+	funcGenerateToken          func(user models.User) (s1 string, err error)
+	inspectFuncGenerateToken   func(user models.User)
+	afterGenerateTokenCounter  uint64
+	beforeGenerateTokenCounter uint64
+	GenerateTokenMock          mAuthServiceMockGenerateToken
+
+	funcGetClaims          func(fctx *fiber.Ctx) (m1 jwt.MapClaims)
+	inspectFuncGetClaims   func(fctx *fiber.Ctx)
+	afterGetClaimsCounter  uint64
+	beforeGetClaimsCounter uint64
+	GetClaimsMock          mAuthServiceMockGetClaims
+
+	funcIsCorrectPassword          func(password string, hash string) (b1 bool)
+	inspectFuncIsCorrectPassword   func(password string, hash string)
+	afterIsCorrectPasswordCounter  uint64
+	beforeIsCorrectPasswordCounter uint64
+	IsCorrectPasswordMock          mAuthServiceMockIsCorrectPassword
+}
+
+// NewAuthServiceMock returns a mock for auth.AuthService
+func NewAuthServiceMock(t minimock.Tester) *AuthServiceMock {
+	m := &AuthServiceMock{t: t}
+
+	if controller, ok := t.(minimock.MockController); ok {
+		controller.RegisterMocker(m)
+	}
+
+	m.GenerateTokenMock = mAuthServiceMockGenerateToken{mock: m}
+	m.GenerateTokenMock.callArgs = []*AuthServiceMockGenerateTokenParams{}
+
+	m.GetClaimsMock = mAuthServiceMockGetClaims{mock: m}
+	m.GetClaimsMock.callArgs = []*AuthServiceMockGetClaimsParams{}
+
+	m.IsCorrectPasswordMock = mAuthServiceMockIsCorrectPassword{mock: m}
+	m.IsCorrectPasswordMock.callArgs = []*AuthServiceMockIsCorrectPasswordParams{}
+
+	t.Cleanup(m.MinimockFinish)
+
+	return m
+}
+
+type mAuthServiceMockGenerateToken struct {
+	optional           bool
+	mock               *AuthServiceMock
+	defaultExpectation *AuthServiceMockGenerateTokenExpectation
+	expectations       []*AuthServiceMockGenerateTokenExpectation
+
+	callArgs []*AuthServiceMockGenerateTokenParams
+	mutex    sync.RWMutex
+
+	expectedInvocations uint64
+}
+
+// AuthServiceMockGenerateTokenExpectation specifies expectation struct of the AuthService.GenerateToken
+type AuthServiceMockGenerateTokenExpectation struct {
+	mock      *AuthServiceMock
+	params    *AuthServiceMockGenerateTokenParams
+	paramPtrs *AuthServiceMockGenerateTokenParamPtrs
+	results   *AuthServiceMockGenerateTokenResults
+	Counter   uint64
+}
+
+// AuthServiceMockGenerateTokenParams contains parameters of the AuthService.GenerateToken
+type AuthServiceMockGenerateTokenParams struct {
+	user models.User
+}
+
+// AuthServiceMockGenerateTokenParamPtrs contains pointers to parameters of the AuthService.GenerateToken
+type AuthServiceMockGenerateTokenParamPtrs struct {
+	user *models.User
+}
+
+// AuthServiceMockGenerateTokenResults contains results of the AuthService.GenerateToken
+type AuthServiceMockGenerateTokenResults struct {
+	s1  string
+	err error
+}
+
+// Marks this method to be optional. The default behavior of any method with Return() is '1 or more', meaning
+// the test will fail minimock's automatic final call check if the mocked method was not called at least once.
+// Optional() makes method check to work in '0 or more' mode.
+// It is NOT RECOMMENDED to use this option unless you really need it, as default behaviour helps to
+// catch the problems when the expected method call is totally skipped during test run.
+func (mmGenerateToken *mAuthServiceMockGenerateToken) Optional() *mAuthServiceMockGenerateToken {
+	mmGenerateToken.optional = true
+	return mmGenerateToken
+}
+
+// Expect sets up expected params for AuthService.GenerateToken
+func (mmGenerateToken *mAuthServiceMockGenerateToken) Expect(user models.User) *mAuthServiceMockGenerateToken {
+	if mmGenerateToken.mock.funcGenerateToken != nil {
+		mmGenerateToken.mock.t.Fatalf("AuthServiceMock.GenerateToken mock is already set by Set")
+	}
+
+	if mmGenerateToken.defaultExpectation == nil {
+		mmGenerateToken.defaultExpectation = &AuthServiceMockGenerateTokenExpectation{}
+	}
+
+	if mmGenerateToken.defaultExpectation.paramPtrs != nil {
+		mmGenerateToken.mock.t.Fatalf("AuthServiceMock.GenerateToken mock is already set by ExpectParams functions")
+	}
+
+	mmGenerateToken.defaultExpectation.params = &AuthServiceMockGenerateTokenParams{user}
+	for _, e := range mmGenerateToken.expectations {
+		if minimock.Equal(e.params, mmGenerateToken.defaultExpectation.params) {
+			mmGenerateToken.mock.t.Fatalf("Expectation set by When has same params: %#v", *mmGenerateToken.defaultExpectation.params)
+		}
+	}
+
+	return mmGenerateToken
+}
+
+// ExpectUserParam1 sets up expected param user for AuthService.GenerateToken
+func (mmGenerateToken *mAuthServiceMockGenerateToken) ExpectUserParam1(user models.User) *mAuthServiceMockGenerateToken {
+	if mmGenerateToken.mock.funcGenerateToken != nil {
+		mmGenerateToken.mock.t.Fatalf("AuthServiceMock.GenerateToken mock is already set by Set")
+	}
+
+	if mmGenerateToken.defaultExpectation == nil {
+		mmGenerateToken.defaultExpectation = &AuthServiceMockGenerateTokenExpectation{}
+	}
+
+	if mmGenerateToken.defaultExpectation.params != nil {
+		mmGenerateToken.mock.t.Fatalf("AuthServiceMock.GenerateToken mock is already set by Expect")
+	}
+
+	if mmGenerateToken.defaultExpectation.paramPtrs == nil {
+		mmGenerateToken.defaultExpectation.paramPtrs = &AuthServiceMockGenerateTokenParamPtrs{}
+	}
+	mmGenerateToken.defaultExpectation.paramPtrs.user = &user
+
+	return mmGenerateToken
+}
+
+// Inspect accepts an inspector function that has same arguments as the AuthService.GenerateToken
+func (mmGenerateToken *mAuthServiceMockGenerateToken) Inspect(f func(user models.User)) *mAuthServiceMockGenerateToken {
+	if mmGenerateToken.mock.inspectFuncGenerateToken != nil {
+		mmGenerateToken.mock.t.Fatalf("Inspect function is already set for AuthServiceMock.GenerateToken")
+	}
+
+	mmGenerateToken.mock.inspectFuncGenerateToken = f
+
+	return mmGenerateToken
+}
+
+// Return sets up results that will be returned by AuthService.GenerateToken
+func (mmGenerateToken *mAuthServiceMockGenerateToken) Return(s1 string, err error) *AuthServiceMock {
+	if mmGenerateToken.mock.funcGenerateToken != nil {
+		mmGenerateToken.mock.t.Fatalf("AuthServiceMock.GenerateToken mock is already set by Set")
+	}
+
+	if mmGenerateToken.defaultExpectation == nil {
+		mmGenerateToken.defaultExpectation = &AuthServiceMockGenerateTokenExpectation{mock: mmGenerateToken.mock}
+	}
+	mmGenerateToken.defaultExpectation.results = &AuthServiceMockGenerateTokenResults{s1, err}
+	return mmGenerateToken.mock
+}
+
+// Set uses given function f to mock the AuthService.GenerateToken method
+func (mmGenerateToken *mAuthServiceMockGenerateToken) Set(f func(user models.User) (s1 string, err error)) *AuthServiceMock {
+	if mmGenerateToken.defaultExpectation != nil {
+		mmGenerateToken.mock.t.Fatalf("Default expectation is already set for the AuthService.GenerateToken method")
+	}
+
+	if len(mmGenerateToken.expectations) > 0 {
+		mmGenerateToken.mock.t.Fatalf("Some expectations are already set for the AuthService.GenerateToken method")
+	}
+
+	mmGenerateToken.mock.funcGenerateToken = f
+	return mmGenerateToken.mock
+}
+
+// When sets expectation for the AuthService.GenerateToken which will trigger the result defined by the following
+// Then helper
+func (mmGenerateToken *mAuthServiceMockGenerateToken) When(user models.User) *AuthServiceMockGenerateTokenExpectation {
+	if mmGenerateToken.mock.funcGenerateToken != nil {
+		mmGenerateToken.mock.t.Fatalf("AuthServiceMock.GenerateToken mock is already set by Set")
+	}
+
+	expectation := &AuthServiceMockGenerateTokenExpectation{
+		mock:   mmGenerateToken.mock,
+		params: &AuthServiceMockGenerateTokenParams{user},
+	}
+	mmGenerateToken.expectations = append(mmGenerateToken.expectations, expectation)
+	return expectation
+}
+
+// Then sets up AuthService.GenerateToken return parameters for the expectation previously defined by the When method
+func (e *AuthServiceMockGenerateTokenExpectation) Then(s1 string, err error) *AuthServiceMock {
+	e.results = &AuthServiceMockGenerateTokenResults{s1, err}
+	return e.mock
+}
+
+// Times sets number of times AuthService.GenerateToken should be invoked
+func (mmGenerateToken *mAuthServiceMockGenerateToken) Times(n uint64) *mAuthServiceMockGenerateToken {
+	if n == 0 {
+		mmGenerateToken.mock.t.Fatalf("Times of AuthServiceMock.GenerateToken mock can not be zero")
+	}
+	mm_atomic.StoreUint64(&mmGenerateToken.expectedInvocations, n)
+	return mmGenerateToken
+}
+
+func (mmGenerateToken *mAuthServiceMockGenerateToken) invocationsDone() bool {
+	if len(mmGenerateToken.expectations) == 0 && mmGenerateToken.defaultExpectation == nil && mmGenerateToken.mock.funcGenerateToken == nil {
+		return true
+	}
+
+	totalInvocations := mm_atomic.LoadUint64(&mmGenerateToken.mock.afterGenerateTokenCounter)
+	expectedInvocations := mm_atomic.LoadUint64(&mmGenerateToken.expectedInvocations)
+
+	return totalInvocations > 0 && (expectedInvocations == 0 || expectedInvocations == totalInvocations)
+}
+
+// GenerateToken implements auth.AuthService
+func (mmGenerateToken *AuthServiceMock) GenerateToken(user models.User) (s1 string, err error) {
+	mm_atomic.AddUint64(&mmGenerateToken.beforeGenerateTokenCounter, 1)
+	defer mm_atomic.AddUint64(&mmGenerateToken.afterGenerateTokenCounter, 1)
+
+	if mmGenerateToken.inspectFuncGenerateToken != nil {
+		mmGenerateToken.inspectFuncGenerateToken(user)
+	}
+
+	mm_params := AuthServiceMockGenerateTokenParams{user}
+
+	// Record call args
+	mmGenerateToken.GenerateTokenMock.mutex.Lock()
+	mmGenerateToken.GenerateTokenMock.callArgs = append(mmGenerateToken.GenerateTokenMock.callArgs, &mm_params)
+	mmGenerateToken.GenerateTokenMock.mutex.Unlock()
+
+	for _, e := range mmGenerateToken.GenerateTokenMock.expectations {
+		if minimock.Equal(*e.params, mm_params) {
+			mm_atomic.AddUint64(&e.Counter, 1)
+			return e.results.s1, e.results.err
+		}
+	}
+
+	if mmGenerateToken.GenerateTokenMock.defaultExpectation != nil {
+		mm_atomic.AddUint64(&mmGenerateToken.GenerateTokenMock.defaultExpectation.Counter, 1)
+		mm_want := mmGenerateToken.GenerateTokenMock.defaultExpectation.params
+		mm_want_ptrs := mmGenerateToken.GenerateTokenMock.defaultExpectation.paramPtrs
+
+		mm_got := AuthServiceMockGenerateTokenParams{user}
+
+		if mm_want_ptrs != nil {
+
+			if mm_want_ptrs.user != nil && !minimock.Equal(*mm_want_ptrs.user, mm_got.user) {
+				mmGenerateToken.t.Errorf("AuthServiceMock.GenerateToken got unexpected parameter user, want: %#v, got: %#v%s\n", *mm_want_ptrs.user, mm_got.user, minimock.Diff(*mm_want_ptrs.user, mm_got.user))
+			}
+
+		} else if mm_want != nil && !minimock.Equal(*mm_want, mm_got) {
+			mmGenerateToken.t.Errorf("AuthServiceMock.GenerateToken got unexpected parameters, want: %#v, got: %#v%s\n", *mm_want, mm_got, minimock.Diff(*mm_want, mm_got))
+		}
+
+		mm_results := mmGenerateToken.GenerateTokenMock.defaultExpectation.results
+		if mm_results == nil {
+			mmGenerateToken.t.Fatal("No results are set for the AuthServiceMock.GenerateToken")
+		}
+		return (*mm_results).s1, (*mm_results).err
+	}
+	if mmGenerateToken.funcGenerateToken != nil {
+		return mmGenerateToken.funcGenerateToken(user)
+	}
+	mmGenerateToken.t.Fatalf("Unexpected call to AuthServiceMock.GenerateToken. %v", user)
+	return
+}
+
+// GenerateTokenAfterCounter returns a count of finished AuthServiceMock.GenerateToken invocations
+func (mmGenerateToken *AuthServiceMock) GenerateTokenAfterCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmGenerateToken.afterGenerateTokenCounter)
+}
+
+// GenerateTokenBeforeCounter returns a count of AuthServiceMock.GenerateToken invocations
+func (mmGenerateToken *AuthServiceMock) GenerateTokenBeforeCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmGenerateToken.beforeGenerateTokenCounter)
+}
+
+// Calls returns a list of arguments used in each call to AuthServiceMock.GenerateToken.
+// The list is in the same order as the calls were made (i.e. recent calls have a higher index)
+func (mmGenerateToken *mAuthServiceMockGenerateToken) Calls() []*AuthServiceMockGenerateTokenParams {
+	mmGenerateToken.mutex.RLock()
+
+	argCopy := make([]*AuthServiceMockGenerateTokenParams, len(mmGenerateToken.callArgs))
+	copy(argCopy, mmGenerateToken.callArgs)
+
+	mmGenerateToken.mutex.RUnlock()
+
+	return argCopy
+}
+
+// MinimockGenerateTokenDone returns true if the count of the GenerateToken invocations corresponds
+// the number of defined expectations
+func (m *AuthServiceMock) MinimockGenerateTokenDone() bool {
+	if m.GenerateTokenMock.optional {
+		// Optional methods provide '0 or more' call count restriction.
+		return true
+	}
+
+	for _, e := range m.GenerateTokenMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			return false
+		}
+	}
+
+	return m.GenerateTokenMock.invocationsDone()
+}
+
+// MinimockGenerateTokenInspect logs each unmet expectation
+func (m *AuthServiceMock) MinimockGenerateTokenInspect() {
+	for _, e := range m.GenerateTokenMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			m.t.Errorf("Expected call to AuthServiceMock.GenerateToken with params: %#v", *e.params)
+		}
+	}
+
+	afterGenerateTokenCounter := mm_atomic.LoadUint64(&m.afterGenerateTokenCounter)
+	// if default expectation was set then invocations count should be greater than zero
+	if m.GenerateTokenMock.defaultExpectation != nil && afterGenerateTokenCounter < 1 {
+		if m.GenerateTokenMock.defaultExpectation.params == nil {
+			m.t.Error("Expected call to AuthServiceMock.GenerateToken")
+		} else {
+			m.t.Errorf("Expected call to AuthServiceMock.GenerateToken with params: %#v", *m.GenerateTokenMock.defaultExpectation.params)
+		}
+	}
+	// if func was set then invocations count should be greater than zero
+	if m.funcGenerateToken != nil && afterGenerateTokenCounter < 1 {
+		m.t.Error("Expected call to AuthServiceMock.GenerateToken")
+	}
+
+	if !m.GenerateTokenMock.invocationsDone() && afterGenerateTokenCounter > 0 {
+		m.t.Errorf("Expected %d calls to AuthServiceMock.GenerateToken but found %d calls",
+			mm_atomic.LoadUint64(&m.GenerateTokenMock.expectedInvocations), afterGenerateTokenCounter)
+	}
+}
+
+type mAuthServiceMockGetClaims struct {
+	optional           bool
+	mock               *AuthServiceMock
+	defaultExpectation *AuthServiceMockGetClaimsExpectation
+	expectations       []*AuthServiceMockGetClaimsExpectation
+
+	callArgs []*AuthServiceMockGetClaimsParams
+	mutex    sync.RWMutex
+
+	expectedInvocations uint64
+}
+
+// AuthServiceMockGetClaimsExpectation specifies expectation struct of the AuthService.GetClaims
+type AuthServiceMockGetClaimsExpectation struct {
+	mock      *AuthServiceMock
+	params    *AuthServiceMockGetClaimsParams
+	paramPtrs *AuthServiceMockGetClaimsParamPtrs
+	results   *AuthServiceMockGetClaimsResults
+	Counter   uint64
+}
+
+// AuthServiceMockGetClaimsParams contains parameters of the AuthService.GetClaims
+type AuthServiceMockGetClaimsParams struct {
+	fctx *fiber.Ctx
+}
+
+// AuthServiceMockGetClaimsParamPtrs contains pointers to parameters of the AuthService.GetClaims
+type AuthServiceMockGetClaimsParamPtrs struct {
+	fctx **fiber.Ctx
+}
+
+// AuthServiceMockGetClaimsResults contains results of the AuthService.GetClaims
+type AuthServiceMockGetClaimsResults struct {
+	m1 jwt.MapClaims
+}
+
+// Marks this method to be optional. The default behavior of any method with Return() is '1 or more', meaning
+// the test will fail minimock's automatic final call check if the mocked method was not called at least once.
+// Optional() makes method check to work in '0 or more' mode.
+// It is NOT RECOMMENDED to use this option unless you really need it, as default behaviour helps to
+// catch the problems when the expected method call is totally skipped during test run.
+func (mmGetClaims *mAuthServiceMockGetClaims) Optional() *mAuthServiceMockGetClaims {
+	mmGetClaims.optional = true
+	return mmGetClaims
+}
+
+// Expect sets up expected params for AuthService.GetClaims
+func (mmGetClaims *mAuthServiceMockGetClaims) Expect(fctx *fiber.Ctx) *mAuthServiceMockGetClaims {
+	if mmGetClaims.mock.funcGetClaims != nil {
+		mmGetClaims.mock.t.Fatalf("AuthServiceMock.GetClaims mock is already set by Set")
+	}
+
+	if mmGetClaims.defaultExpectation == nil {
+		mmGetClaims.defaultExpectation = &AuthServiceMockGetClaimsExpectation{}
+	}
+
+	if mmGetClaims.defaultExpectation.paramPtrs != nil {
+		mmGetClaims.mock.t.Fatalf("AuthServiceMock.GetClaims mock is already set by ExpectParams functions")
+	}
+
+	mmGetClaims.defaultExpectation.params = &AuthServiceMockGetClaimsParams{fctx}
+	for _, e := range mmGetClaims.expectations {
+		if minimock.Equal(e.params, mmGetClaims.defaultExpectation.params) {
+			mmGetClaims.mock.t.Fatalf("Expectation set by When has same params: %#v", *mmGetClaims.defaultExpectation.params)
+		}
+	}
+
+	return mmGetClaims
+}
+
+// ExpectFctxParam1 sets up expected param fctx for AuthService.GetClaims
+func (mmGetClaims *mAuthServiceMockGetClaims) ExpectFctxParam1(fctx *fiber.Ctx) *mAuthServiceMockGetClaims {
+	if mmGetClaims.mock.funcGetClaims != nil {
+		mmGetClaims.mock.t.Fatalf("AuthServiceMock.GetClaims mock is already set by Set")
+	}
+
+	if mmGetClaims.defaultExpectation == nil {
+		mmGetClaims.defaultExpectation = &AuthServiceMockGetClaimsExpectation{}
+	}
+
+	if mmGetClaims.defaultExpectation.params != nil {
+		mmGetClaims.mock.t.Fatalf("AuthServiceMock.GetClaims mock is already set by Expect")
+	}
+
+	if mmGetClaims.defaultExpectation.paramPtrs == nil {
+		mmGetClaims.defaultExpectation.paramPtrs = &AuthServiceMockGetClaimsParamPtrs{}
+	}
+	mmGetClaims.defaultExpectation.paramPtrs.fctx = &fctx
+
+	return mmGetClaims
+}
+
+// Inspect accepts an inspector function that has same arguments as the AuthService.GetClaims
+func (mmGetClaims *mAuthServiceMockGetClaims) Inspect(f func(fctx *fiber.Ctx)) *mAuthServiceMockGetClaims {
+	if mmGetClaims.mock.inspectFuncGetClaims != nil {
+		mmGetClaims.mock.t.Fatalf("Inspect function is already set for AuthServiceMock.GetClaims")
+	}
+
+	mmGetClaims.mock.inspectFuncGetClaims = f
+
+	return mmGetClaims
+}
+
+// Return sets up results that will be returned by AuthService.GetClaims
+func (mmGetClaims *mAuthServiceMockGetClaims) Return(m1 jwt.MapClaims) *AuthServiceMock {
+	if mmGetClaims.mock.funcGetClaims != nil {
+		mmGetClaims.mock.t.Fatalf("AuthServiceMock.GetClaims mock is already set by Set")
+	}
+
+	if mmGetClaims.defaultExpectation == nil {
+		mmGetClaims.defaultExpectation = &AuthServiceMockGetClaimsExpectation{mock: mmGetClaims.mock}
+	}
+	mmGetClaims.defaultExpectation.results = &AuthServiceMockGetClaimsResults{m1}
+	return mmGetClaims.mock
+}
+
+// Set uses given function f to mock the AuthService.GetClaims method
+func (mmGetClaims *mAuthServiceMockGetClaims) Set(f func(fctx *fiber.Ctx) (m1 jwt.MapClaims)) *AuthServiceMock {
+	if mmGetClaims.defaultExpectation != nil {
+		mmGetClaims.mock.t.Fatalf("Default expectation is already set for the AuthService.GetClaims method")
+	}
+
+	if len(mmGetClaims.expectations) > 0 {
+		mmGetClaims.mock.t.Fatalf("Some expectations are already set for the AuthService.GetClaims method")
+	}
+
+	mmGetClaims.mock.funcGetClaims = f
+	return mmGetClaims.mock
+}
+
+// When sets expectation for the AuthService.GetClaims which will trigger the result defined by the following
+// Then helper
+func (mmGetClaims *mAuthServiceMockGetClaims) When(fctx *fiber.Ctx) *AuthServiceMockGetClaimsExpectation {
+	if mmGetClaims.mock.funcGetClaims != nil {
+		mmGetClaims.mock.t.Fatalf("AuthServiceMock.GetClaims mock is already set by Set")
+	}
+
+	expectation := &AuthServiceMockGetClaimsExpectation{
+		mock:   mmGetClaims.mock,
+		params: &AuthServiceMockGetClaimsParams{fctx},
+	}
+	mmGetClaims.expectations = append(mmGetClaims.expectations, expectation)
+	return expectation
+}
+
+// Then sets up AuthService.GetClaims return parameters for the expectation previously defined by the When method
+func (e *AuthServiceMockGetClaimsExpectation) Then(m1 jwt.MapClaims) *AuthServiceMock {
+	e.results = &AuthServiceMockGetClaimsResults{m1}
+	return e.mock
+}
+
+// Times sets number of times AuthService.GetClaims should be invoked
+func (mmGetClaims *mAuthServiceMockGetClaims) Times(n uint64) *mAuthServiceMockGetClaims {
+	if n == 0 {
+		mmGetClaims.mock.t.Fatalf("Times of AuthServiceMock.GetClaims mock can not be zero")
+	}
+	mm_atomic.StoreUint64(&mmGetClaims.expectedInvocations, n)
+	return mmGetClaims
+}
+
+func (mmGetClaims *mAuthServiceMockGetClaims) invocationsDone() bool {
+	if len(mmGetClaims.expectations) == 0 && mmGetClaims.defaultExpectation == nil && mmGetClaims.mock.funcGetClaims == nil {
+		return true
+	}
+
+	totalInvocations := mm_atomic.LoadUint64(&mmGetClaims.mock.afterGetClaimsCounter)
+	expectedInvocations := mm_atomic.LoadUint64(&mmGetClaims.expectedInvocations)
+
+	return totalInvocations > 0 && (expectedInvocations == 0 || expectedInvocations == totalInvocations)
+}
+
+// GetClaims implements auth.AuthService
+func (mmGetClaims *AuthServiceMock) GetClaims(fctx *fiber.Ctx) (m1 jwt.MapClaims) {
+	mm_atomic.AddUint64(&mmGetClaims.beforeGetClaimsCounter, 1)
+	defer mm_atomic.AddUint64(&mmGetClaims.afterGetClaimsCounter, 1)
+
+	if mmGetClaims.inspectFuncGetClaims != nil {
+		mmGetClaims.inspectFuncGetClaims(fctx)
+	}
+
+	mm_params := AuthServiceMockGetClaimsParams{fctx}
+
+	// Record call args
+	mmGetClaims.GetClaimsMock.mutex.Lock()
+	mmGetClaims.GetClaimsMock.callArgs = append(mmGetClaims.GetClaimsMock.callArgs, &mm_params)
+	mmGetClaims.GetClaimsMock.mutex.Unlock()
+
+	for _, e := range mmGetClaims.GetClaimsMock.expectations {
+		if minimock.Equal(*e.params, mm_params) {
+			mm_atomic.AddUint64(&e.Counter, 1)
+			return e.results.m1
+		}
+	}
+
+	if mmGetClaims.GetClaimsMock.defaultExpectation != nil {
+		mm_atomic.AddUint64(&mmGetClaims.GetClaimsMock.defaultExpectation.Counter, 1)
+		mm_want := mmGetClaims.GetClaimsMock.defaultExpectation.params
+		mm_want_ptrs := mmGetClaims.GetClaimsMock.defaultExpectation.paramPtrs
+
+		mm_got := AuthServiceMockGetClaimsParams{fctx}
+
+		if mm_want_ptrs != nil {
+
+			if mm_want_ptrs.fctx != nil && !minimock.Equal(*mm_want_ptrs.fctx, mm_got.fctx) {
+				mmGetClaims.t.Errorf("AuthServiceMock.GetClaims got unexpected parameter fctx, want: %#v, got: %#v%s\n", *mm_want_ptrs.fctx, mm_got.fctx, minimock.Diff(*mm_want_ptrs.fctx, mm_got.fctx))
+			}
+
+		} else if mm_want != nil && !minimock.Equal(*mm_want, mm_got) {
+			mmGetClaims.t.Errorf("AuthServiceMock.GetClaims got unexpected parameters, want: %#v, got: %#v%s\n", *mm_want, mm_got, minimock.Diff(*mm_want, mm_got))
+		}
+
+		mm_results := mmGetClaims.GetClaimsMock.defaultExpectation.results
+		if mm_results == nil {
+			mmGetClaims.t.Fatal("No results are set for the AuthServiceMock.GetClaims")
+		}
+		return (*mm_results).m1
+	}
+	if mmGetClaims.funcGetClaims != nil {
+		return mmGetClaims.funcGetClaims(fctx)
+	}
+	mmGetClaims.t.Fatalf("Unexpected call to AuthServiceMock.GetClaims. %v", fctx)
+	return
+}
+
+// GetClaimsAfterCounter returns a count of finished AuthServiceMock.GetClaims invocations
+func (mmGetClaims *AuthServiceMock) GetClaimsAfterCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmGetClaims.afterGetClaimsCounter)
+}
+
+// GetClaimsBeforeCounter returns a count of AuthServiceMock.GetClaims invocations
+func (mmGetClaims *AuthServiceMock) GetClaimsBeforeCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmGetClaims.beforeGetClaimsCounter)
+}
+
+// Calls returns a list of arguments used in each call to AuthServiceMock.GetClaims.
+// The list is in the same order as the calls were made (i.e. recent calls have a higher index)
+func (mmGetClaims *mAuthServiceMockGetClaims) Calls() []*AuthServiceMockGetClaimsParams {
+	mmGetClaims.mutex.RLock()
+
+	argCopy := make([]*AuthServiceMockGetClaimsParams, len(mmGetClaims.callArgs))
+	copy(argCopy, mmGetClaims.callArgs)
+
+	mmGetClaims.mutex.RUnlock()
+
+	return argCopy
+}
+
+// MinimockGetClaimsDone returns true if the count of the GetClaims invocations corresponds
+// the number of defined expectations
+func (m *AuthServiceMock) MinimockGetClaimsDone() bool {
+	if m.GetClaimsMock.optional {
+		// Optional methods provide '0 or more' call count restriction.
+		return true
+	}
+
+	for _, e := range m.GetClaimsMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			return false
+		}
+	}
+
+	return m.GetClaimsMock.invocationsDone()
+}
+
+// MinimockGetClaimsInspect logs each unmet expectation
+func (m *AuthServiceMock) MinimockGetClaimsInspect() {
+	for _, e := range m.GetClaimsMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			m.t.Errorf("Expected call to AuthServiceMock.GetClaims with params: %#v", *e.params)
+		}
+	}
+
+	afterGetClaimsCounter := mm_atomic.LoadUint64(&m.afterGetClaimsCounter)
+	// if default expectation was set then invocations count should be greater than zero
+	if m.GetClaimsMock.defaultExpectation != nil && afterGetClaimsCounter < 1 {
+		if m.GetClaimsMock.defaultExpectation.params == nil {
+			m.t.Error("Expected call to AuthServiceMock.GetClaims")
+		} else {
+			m.t.Errorf("Expected call to AuthServiceMock.GetClaims with params: %#v", *m.GetClaimsMock.defaultExpectation.params)
+		}
+	}
+	// if func was set then invocations count should be greater than zero
+	if m.funcGetClaims != nil && afterGetClaimsCounter < 1 {
+		m.t.Error("Expected call to AuthServiceMock.GetClaims")
+	}
+
+	if !m.GetClaimsMock.invocationsDone() && afterGetClaimsCounter > 0 {
+		m.t.Errorf("Expected %d calls to AuthServiceMock.GetClaims but found %d calls",
+			mm_atomic.LoadUint64(&m.GetClaimsMock.expectedInvocations), afterGetClaimsCounter)
+	}
+}
+
+type mAuthServiceMockIsCorrectPassword struct {
+	optional           bool
+	mock               *AuthServiceMock
+	defaultExpectation *AuthServiceMockIsCorrectPasswordExpectation
+	expectations       []*AuthServiceMockIsCorrectPasswordExpectation
+
+	callArgs []*AuthServiceMockIsCorrectPasswordParams
+	mutex    sync.RWMutex
+
+	expectedInvocations uint64
+}
+
+// AuthServiceMockIsCorrectPasswordExpectation specifies expectation struct of the AuthService.IsCorrectPassword
+type AuthServiceMockIsCorrectPasswordExpectation struct {
+	mock      *AuthServiceMock
+	params    *AuthServiceMockIsCorrectPasswordParams
+	paramPtrs *AuthServiceMockIsCorrectPasswordParamPtrs
+	results   *AuthServiceMockIsCorrectPasswordResults
+	Counter   uint64
+}
+
+// AuthServiceMockIsCorrectPasswordParams contains parameters of the AuthService.IsCorrectPassword
+type AuthServiceMockIsCorrectPasswordParams struct {
+	password string
+	hash     string
+}
+
+// AuthServiceMockIsCorrectPasswordParamPtrs contains pointers to parameters of the AuthService.IsCorrectPassword
+type AuthServiceMockIsCorrectPasswordParamPtrs struct {
+	password *string
+	hash     *string
+}
+
+// AuthServiceMockIsCorrectPasswordResults contains results of the AuthService.IsCorrectPassword
+type AuthServiceMockIsCorrectPasswordResults struct {
+	b1 bool
+}
+
+// Marks this method to be optional. The default behavior of any method with Return() is '1 or more', meaning
+// the test will fail minimock's automatic final call check if the mocked method was not called at least once.
+// Optional() makes method check to work in '0 or more' mode.
+// It is NOT RECOMMENDED to use this option unless you really need it, as default behaviour helps to
+// catch the problems when the expected method call is totally skipped during test run.
+func (mmIsCorrectPassword *mAuthServiceMockIsCorrectPassword) Optional() *mAuthServiceMockIsCorrectPassword {
+	mmIsCorrectPassword.optional = true
+	return mmIsCorrectPassword
+}
+
+// Expect sets up expected params for AuthService.IsCorrectPassword
+func (mmIsCorrectPassword *mAuthServiceMockIsCorrectPassword) Expect(password string, hash string) *mAuthServiceMockIsCorrectPassword {
+	if mmIsCorrectPassword.mock.funcIsCorrectPassword != nil {
+		mmIsCorrectPassword.mock.t.Fatalf("AuthServiceMock.IsCorrectPassword mock is already set by Set")
+	}
+
+	if mmIsCorrectPassword.defaultExpectation == nil {
+		mmIsCorrectPassword.defaultExpectation = &AuthServiceMockIsCorrectPasswordExpectation{}
+	}
+
+	if mmIsCorrectPassword.defaultExpectation.paramPtrs != nil {
+		mmIsCorrectPassword.mock.t.Fatalf("AuthServiceMock.IsCorrectPassword mock is already set by ExpectParams functions")
+	}
+
+	mmIsCorrectPassword.defaultExpectation.params = &AuthServiceMockIsCorrectPasswordParams{password, hash}
+	for _, e := range mmIsCorrectPassword.expectations {
+		if minimock.Equal(e.params, mmIsCorrectPassword.defaultExpectation.params) {
+			mmIsCorrectPassword.mock.t.Fatalf("Expectation set by When has same params: %#v", *mmIsCorrectPassword.defaultExpectation.params)
+		}
+	}
+
+	return mmIsCorrectPassword
+}
+
+// ExpectPasswordParam1 sets up expected param password for AuthService.IsCorrectPassword
+func (mmIsCorrectPassword *mAuthServiceMockIsCorrectPassword) ExpectPasswordParam1(password string) *mAuthServiceMockIsCorrectPassword {
+	if mmIsCorrectPassword.mock.funcIsCorrectPassword != nil {
+		mmIsCorrectPassword.mock.t.Fatalf("AuthServiceMock.IsCorrectPassword mock is already set by Set")
+	}
+
+	if mmIsCorrectPassword.defaultExpectation == nil {
+		mmIsCorrectPassword.defaultExpectation = &AuthServiceMockIsCorrectPasswordExpectation{}
+	}
+
+	if mmIsCorrectPassword.defaultExpectation.params != nil {
+		mmIsCorrectPassword.mock.t.Fatalf("AuthServiceMock.IsCorrectPassword mock is already set by Expect")
+	}
+
+	if mmIsCorrectPassword.defaultExpectation.paramPtrs == nil {
+		mmIsCorrectPassword.defaultExpectation.paramPtrs = &AuthServiceMockIsCorrectPasswordParamPtrs{}
+	}
+	mmIsCorrectPassword.defaultExpectation.paramPtrs.password = &password
+
+	return mmIsCorrectPassword
+}
+
+// ExpectHashParam2 sets up expected param hash for AuthService.IsCorrectPassword
+func (mmIsCorrectPassword *mAuthServiceMockIsCorrectPassword) ExpectHashParam2(hash string) *mAuthServiceMockIsCorrectPassword {
+	if mmIsCorrectPassword.mock.funcIsCorrectPassword != nil {
+		mmIsCorrectPassword.mock.t.Fatalf("AuthServiceMock.IsCorrectPassword mock is already set by Set")
+	}
+
+	if mmIsCorrectPassword.defaultExpectation == nil {
+		mmIsCorrectPassword.defaultExpectation = &AuthServiceMockIsCorrectPasswordExpectation{}
+	}
+
+	if mmIsCorrectPassword.defaultExpectation.params != nil {
+		mmIsCorrectPassword.mock.t.Fatalf("AuthServiceMock.IsCorrectPassword mock is already set by Expect")
+	}
+
+	if mmIsCorrectPassword.defaultExpectation.paramPtrs == nil {
+		mmIsCorrectPassword.defaultExpectation.paramPtrs = &AuthServiceMockIsCorrectPasswordParamPtrs{}
+	}
+	mmIsCorrectPassword.defaultExpectation.paramPtrs.hash = &hash
+
+	return mmIsCorrectPassword
+}
+
+// Inspect accepts an inspector function that has same arguments as the AuthService.IsCorrectPassword
+func (mmIsCorrectPassword *mAuthServiceMockIsCorrectPassword) Inspect(f func(password string, hash string)) *mAuthServiceMockIsCorrectPassword {
+	if mmIsCorrectPassword.mock.inspectFuncIsCorrectPassword != nil {
+		mmIsCorrectPassword.mock.t.Fatalf("Inspect function is already set for AuthServiceMock.IsCorrectPassword")
+	}
+
+	mmIsCorrectPassword.mock.inspectFuncIsCorrectPassword = f
+
+	return mmIsCorrectPassword
+}
+
+// Return sets up results that will be returned by AuthService.IsCorrectPassword
+func (mmIsCorrectPassword *mAuthServiceMockIsCorrectPassword) Return(b1 bool) *AuthServiceMock {
+	if mmIsCorrectPassword.mock.funcIsCorrectPassword != nil {
+		mmIsCorrectPassword.mock.t.Fatalf("AuthServiceMock.IsCorrectPassword mock is already set by Set")
+	}
+
+	if mmIsCorrectPassword.defaultExpectation == nil {
+		mmIsCorrectPassword.defaultExpectation = &AuthServiceMockIsCorrectPasswordExpectation{mock: mmIsCorrectPassword.mock}
+	}
+	mmIsCorrectPassword.defaultExpectation.results = &AuthServiceMockIsCorrectPasswordResults{b1}
+	return mmIsCorrectPassword.mock
+}
+
+// Set uses given function f to mock the AuthService.IsCorrectPassword method
+func (mmIsCorrectPassword *mAuthServiceMockIsCorrectPassword) Set(f func(password string, hash string) (b1 bool)) *AuthServiceMock {
+	if mmIsCorrectPassword.defaultExpectation != nil {
+		mmIsCorrectPassword.mock.t.Fatalf("Default expectation is already set for the AuthService.IsCorrectPassword method")
+	}
+
+	if len(mmIsCorrectPassword.expectations) > 0 {
+		mmIsCorrectPassword.mock.t.Fatalf("Some expectations are already set for the AuthService.IsCorrectPassword method")
+	}
+
+	mmIsCorrectPassword.mock.funcIsCorrectPassword = f
+	return mmIsCorrectPassword.mock
+}
+
+// When sets expectation for the AuthService.IsCorrectPassword which will trigger the result defined by the following
+// Then helper
+func (mmIsCorrectPassword *mAuthServiceMockIsCorrectPassword) When(password string, hash string) *AuthServiceMockIsCorrectPasswordExpectation {
+	if mmIsCorrectPassword.mock.funcIsCorrectPassword != nil {
+		mmIsCorrectPassword.mock.t.Fatalf("AuthServiceMock.IsCorrectPassword mock is already set by Set")
+	}
+
+	expectation := &AuthServiceMockIsCorrectPasswordExpectation{
+		mock:   mmIsCorrectPassword.mock,
+		params: &AuthServiceMockIsCorrectPasswordParams{password, hash},
+	}
+	mmIsCorrectPassword.expectations = append(mmIsCorrectPassword.expectations, expectation)
+	return expectation
+}
+
+// Then sets up AuthService.IsCorrectPassword return parameters for the expectation previously defined by the When method
+func (e *AuthServiceMockIsCorrectPasswordExpectation) Then(b1 bool) *AuthServiceMock {
+	e.results = &AuthServiceMockIsCorrectPasswordResults{b1}
+	return e.mock
+}
+
+// Times sets number of times AuthService.IsCorrectPassword should be invoked
+func (mmIsCorrectPassword *mAuthServiceMockIsCorrectPassword) Times(n uint64) *mAuthServiceMockIsCorrectPassword {
+	if n == 0 {
+		mmIsCorrectPassword.mock.t.Fatalf("Times of AuthServiceMock.IsCorrectPassword mock can not be zero")
+	}
+	mm_atomic.StoreUint64(&mmIsCorrectPassword.expectedInvocations, n)
+	return mmIsCorrectPassword
+}
+
+func (mmIsCorrectPassword *mAuthServiceMockIsCorrectPassword) invocationsDone() bool {
+	if len(mmIsCorrectPassword.expectations) == 0 && mmIsCorrectPassword.defaultExpectation == nil && mmIsCorrectPassword.mock.funcIsCorrectPassword == nil {
+		return true
+	}
+
+	totalInvocations := mm_atomic.LoadUint64(&mmIsCorrectPassword.mock.afterIsCorrectPasswordCounter)
+	expectedInvocations := mm_atomic.LoadUint64(&mmIsCorrectPassword.expectedInvocations)
+
+	return totalInvocations > 0 && (expectedInvocations == 0 || expectedInvocations == totalInvocations)
+}
+
+// IsCorrectPassword implements auth.AuthService
+func (mmIsCorrectPassword *AuthServiceMock) IsCorrectPassword(password string, hash string) (b1 bool) {
+	mm_atomic.AddUint64(&mmIsCorrectPassword.beforeIsCorrectPasswordCounter, 1)
+	defer mm_atomic.AddUint64(&mmIsCorrectPassword.afterIsCorrectPasswordCounter, 1)
+
+	if mmIsCorrectPassword.inspectFuncIsCorrectPassword != nil {
+		mmIsCorrectPassword.inspectFuncIsCorrectPassword(password, hash)
+	}
+
+	mm_params := AuthServiceMockIsCorrectPasswordParams{password, hash}
+
+	// Record call args
+	mmIsCorrectPassword.IsCorrectPasswordMock.mutex.Lock()
+	mmIsCorrectPassword.IsCorrectPasswordMock.callArgs = append(mmIsCorrectPassword.IsCorrectPasswordMock.callArgs, &mm_params)
+	mmIsCorrectPassword.IsCorrectPasswordMock.mutex.Unlock()
+
+	for _, e := range mmIsCorrectPassword.IsCorrectPasswordMock.expectations {
+		if minimock.Equal(*e.params, mm_params) {
+			mm_atomic.AddUint64(&e.Counter, 1)
+			return e.results.b1
+		}
+	}
+
+	if mmIsCorrectPassword.IsCorrectPasswordMock.defaultExpectation != nil {
+		mm_atomic.AddUint64(&mmIsCorrectPassword.IsCorrectPasswordMock.defaultExpectation.Counter, 1)
+		mm_want := mmIsCorrectPassword.IsCorrectPasswordMock.defaultExpectation.params
+		mm_want_ptrs := mmIsCorrectPassword.IsCorrectPasswordMock.defaultExpectation.paramPtrs
+
+		mm_got := AuthServiceMockIsCorrectPasswordParams{password, hash}
+
+		if mm_want_ptrs != nil {
+
+			if mm_want_ptrs.password != nil && !minimock.Equal(*mm_want_ptrs.password, mm_got.password) {
+				mmIsCorrectPassword.t.Errorf("AuthServiceMock.IsCorrectPassword got unexpected parameter password, want: %#v, got: %#v%s\n", *mm_want_ptrs.password, mm_got.password, minimock.Diff(*mm_want_ptrs.password, mm_got.password))
+			}
+
+			if mm_want_ptrs.hash != nil && !minimock.Equal(*mm_want_ptrs.hash, mm_got.hash) {
+				mmIsCorrectPassword.t.Errorf("AuthServiceMock.IsCorrectPassword got unexpected parameter hash, want: %#v, got: %#v%s\n", *mm_want_ptrs.hash, mm_got.hash, minimock.Diff(*mm_want_ptrs.hash, mm_got.hash))
+			}
+
+		} else if mm_want != nil && !minimock.Equal(*mm_want, mm_got) {
+			mmIsCorrectPassword.t.Errorf("AuthServiceMock.IsCorrectPassword got unexpected parameters, want: %#v, got: %#v%s\n", *mm_want, mm_got, minimock.Diff(*mm_want, mm_got))
+		}
+
+		mm_results := mmIsCorrectPassword.IsCorrectPasswordMock.defaultExpectation.results
+		if mm_results == nil {
+			mmIsCorrectPassword.t.Fatal("No results are set for the AuthServiceMock.IsCorrectPassword")
+		}
+		return (*mm_results).b1
+	}
+	if mmIsCorrectPassword.funcIsCorrectPassword != nil {
+		return mmIsCorrectPassword.funcIsCorrectPassword(password, hash)
+	}
+	mmIsCorrectPassword.t.Fatalf("Unexpected call to AuthServiceMock.IsCorrectPassword. %v %v", password, hash)
+	return
+}
+
+// IsCorrectPasswordAfterCounter returns a count of finished AuthServiceMock.IsCorrectPassword invocations
+func (mmIsCorrectPassword *AuthServiceMock) IsCorrectPasswordAfterCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmIsCorrectPassword.afterIsCorrectPasswordCounter)
+}
+
+// IsCorrectPasswordBeforeCounter returns a count of AuthServiceMock.IsCorrectPassword invocations
+func (mmIsCorrectPassword *AuthServiceMock) IsCorrectPasswordBeforeCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmIsCorrectPassword.beforeIsCorrectPasswordCounter)
+}
+
+// Calls returns a list of arguments used in each call to AuthServiceMock.IsCorrectPassword.
+// The list is in the same order as the calls were made (i.e. recent calls have a higher index)
+func (mmIsCorrectPassword *mAuthServiceMockIsCorrectPassword) Calls() []*AuthServiceMockIsCorrectPasswordParams {
+	mmIsCorrectPassword.mutex.RLock()
+
+	argCopy := make([]*AuthServiceMockIsCorrectPasswordParams, len(mmIsCorrectPassword.callArgs))
+	copy(argCopy, mmIsCorrectPassword.callArgs)
+
+	mmIsCorrectPassword.mutex.RUnlock()
+
+	return argCopy
+}
+
+// MinimockIsCorrectPasswordDone returns true if the count of the IsCorrectPassword invocations corresponds
+// the number of defined expectations
+func (m *AuthServiceMock) MinimockIsCorrectPasswordDone() bool {
+	if m.IsCorrectPasswordMock.optional {
+		// Optional methods provide '0 or more' call count restriction.
+		return true
+	}
+
+	for _, e := range m.IsCorrectPasswordMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			return false
+		}
+	}
+
+	return m.IsCorrectPasswordMock.invocationsDone()
+}
+
+// MinimockIsCorrectPasswordInspect logs each unmet expectation
+func (m *AuthServiceMock) MinimockIsCorrectPasswordInspect() {
+	for _, e := range m.IsCorrectPasswordMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			m.t.Errorf("Expected call to AuthServiceMock.IsCorrectPassword with params: %#v", *e.params)
+		}
+	}
+
+	afterIsCorrectPasswordCounter := mm_atomic.LoadUint64(&m.afterIsCorrectPasswordCounter)
+	// if default expectation was set then invocations count should be greater than zero
+	if m.IsCorrectPasswordMock.defaultExpectation != nil && afterIsCorrectPasswordCounter < 1 {
+		if m.IsCorrectPasswordMock.defaultExpectation.params == nil {
+			m.t.Error("Expected call to AuthServiceMock.IsCorrectPassword")
+		} else {
+			m.t.Errorf("Expected call to AuthServiceMock.IsCorrectPassword with params: %#v", *m.IsCorrectPasswordMock.defaultExpectation.params)
+		}
+	}
+	// if func was set then invocations count should be greater than zero
+	if m.funcIsCorrectPassword != nil && afterIsCorrectPasswordCounter < 1 {
+		m.t.Error("Expected call to AuthServiceMock.IsCorrectPassword")
+	}
+
+	if !m.IsCorrectPasswordMock.invocationsDone() && afterIsCorrectPasswordCounter > 0 {
+		m.t.Errorf("Expected %d calls to AuthServiceMock.IsCorrectPassword but found %d calls",
+			mm_atomic.LoadUint64(&m.IsCorrectPasswordMock.expectedInvocations), afterIsCorrectPasswordCounter)
+	}
+}
+
+// MinimockFinish checks that all mocked methods have been called the expected number of times
+func (m *AuthServiceMock) MinimockFinish() {
+	m.finishOnce.Do(func() {
+		if !m.minimockDone() {
+			m.MinimockGenerateTokenInspect()
+
+			m.MinimockGetClaimsInspect()
+
+			m.MinimockIsCorrectPasswordInspect()
+		}
+	})
+}
+
+// MinimockWait waits for all mocked methods to be called the expected number of times
+func (m *AuthServiceMock) MinimockWait(timeout mm_time.Duration) {
+	timeoutCh := mm_time.After(timeout)
+	for {
+		if m.minimockDone() {
+			return
+		}
+		select {
+		case <-timeoutCh:
+			m.MinimockFinish()
+			return
+		case <-mm_time.After(10 * mm_time.Millisecond):
+		}
+	}
+}
+
+func (m *AuthServiceMock) minimockDone() bool {
+	done := true
+	return done &&
+		m.MinimockGenerateTokenDone() &&
+		m.MinimockGetClaimsDone() &&
+		m.MinimockIsCorrectPasswordDone()
+}

+ 395 - 0
internal/api/v1/auth/mocks/user_repository_minimock.go

@@ -0,0 +1,395 @@
+// Code generated by http://github.com/gojuno/minimock (v3.3.13). DO NOT EDIT.
+
+package mocks
+
+//go:generate minimock -i git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/auth.UserRepository -o user_repository_minimock.go -n UserRepositoryMock -p mocks
+
+import (
+	"context"
+	"sync"
+	mm_atomic "sync/atomic"
+	mm_time "time"
+
+	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
+	"github.com/gojuno/minimock/v3"
+)
+
+// UserRepositoryMock implements auth.UserRepository
+type UserRepositoryMock struct {
+	t          minimock.Tester
+	finishOnce sync.Once
+
+	funcGet          func(ctx context.Context, username string) (up1 *models.User, err error)
+	inspectFuncGet   func(ctx context.Context, username string)
+	afterGetCounter  uint64
+	beforeGetCounter uint64
+	GetMock          mUserRepositoryMockGet
+}
+
+// NewUserRepositoryMock returns a mock for auth.UserRepository
+func NewUserRepositoryMock(t minimock.Tester) *UserRepositoryMock {
+	m := &UserRepositoryMock{t: t}
+
+	if controller, ok := t.(minimock.MockController); ok {
+		controller.RegisterMocker(m)
+	}
+
+	m.GetMock = mUserRepositoryMockGet{mock: m}
+	m.GetMock.callArgs = []*UserRepositoryMockGetParams{}
+
+	t.Cleanup(m.MinimockFinish)
+
+	return m
+}
+
+type mUserRepositoryMockGet struct {
+	optional           bool
+	mock               *UserRepositoryMock
+	defaultExpectation *UserRepositoryMockGetExpectation
+	expectations       []*UserRepositoryMockGetExpectation
+
+	callArgs []*UserRepositoryMockGetParams
+	mutex    sync.RWMutex
+
+	expectedInvocations uint64
+}
+
+// UserRepositoryMockGetExpectation specifies expectation struct of the UserRepository.Get
+type UserRepositoryMockGetExpectation struct {
+	mock      *UserRepositoryMock
+	params    *UserRepositoryMockGetParams
+	paramPtrs *UserRepositoryMockGetParamPtrs
+	results   *UserRepositoryMockGetResults
+	Counter   uint64
+}
+
+// UserRepositoryMockGetParams contains parameters of the UserRepository.Get
+type UserRepositoryMockGetParams struct {
+	ctx      context.Context
+	username string
+}
+
+// UserRepositoryMockGetParamPtrs contains pointers to parameters of the UserRepository.Get
+type UserRepositoryMockGetParamPtrs struct {
+	ctx      *context.Context
+	username *string
+}
+
+// UserRepositoryMockGetResults contains results of the UserRepository.Get
+type UserRepositoryMockGetResults struct {
+	up1 *models.User
+	err error
+}
+
+// Marks this method to be optional. The default behavior of any method with Return() is '1 or more', meaning
+// the test will fail minimock's automatic final call check if the mocked method was not called at least once.
+// Optional() makes method check to work in '0 or more' mode.
+// It is NOT RECOMMENDED to use this option unless you really need it, as default behaviour helps to
+// catch the problems when the expected method call is totally skipped during test run.
+func (mmGet *mUserRepositoryMockGet) Optional() *mUserRepositoryMockGet {
+	mmGet.optional = true
+	return mmGet
+}
+
+// Expect sets up expected params for UserRepository.Get
+func (mmGet *mUserRepositoryMockGet) Expect(ctx context.Context, username string) *mUserRepositoryMockGet {
+	if mmGet.mock.funcGet != nil {
+		mmGet.mock.t.Fatalf("UserRepositoryMock.Get mock is already set by Set")
+	}
+
+	if mmGet.defaultExpectation == nil {
+		mmGet.defaultExpectation = &UserRepositoryMockGetExpectation{}
+	}
+
+	if mmGet.defaultExpectation.paramPtrs != nil {
+		mmGet.mock.t.Fatalf("UserRepositoryMock.Get mock is already set by ExpectParams functions")
+	}
+
+	mmGet.defaultExpectation.params = &UserRepositoryMockGetParams{ctx, username}
+	for _, e := range mmGet.expectations {
+		if minimock.Equal(e.params, mmGet.defaultExpectation.params) {
+			mmGet.mock.t.Fatalf("Expectation set by When has same params: %#v", *mmGet.defaultExpectation.params)
+		}
+	}
+
+	return mmGet
+}
+
+// ExpectCtxParam1 sets up expected param ctx for UserRepository.Get
+func (mmGet *mUserRepositoryMockGet) ExpectCtxParam1(ctx context.Context) *mUserRepositoryMockGet {
+	if mmGet.mock.funcGet != nil {
+		mmGet.mock.t.Fatalf("UserRepositoryMock.Get mock is already set by Set")
+	}
+
+	if mmGet.defaultExpectation == nil {
+		mmGet.defaultExpectation = &UserRepositoryMockGetExpectation{}
+	}
+
+	if mmGet.defaultExpectation.params != nil {
+		mmGet.mock.t.Fatalf("UserRepositoryMock.Get mock is already set by Expect")
+	}
+
+	if mmGet.defaultExpectation.paramPtrs == nil {
+		mmGet.defaultExpectation.paramPtrs = &UserRepositoryMockGetParamPtrs{}
+	}
+	mmGet.defaultExpectation.paramPtrs.ctx = &ctx
+
+	return mmGet
+}
+
+// ExpectUsernameParam2 sets up expected param username for UserRepository.Get
+func (mmGet *mUserRepositoryMockGet) ExpectUsernameParam2(username string) *mUserRepositoryMockGet {
+	if mmGet.mock.funcGet != nil {
+		mmGet.mock.t.Fatalf("UserRepositoryMock.Get mock is already set by Set")
+	}
+
+	if mmGet.defaultExpectation == nil {
+		mmGet.defaultExpectation = &UserRepositoryMockGetExpectation{}
+	}
+
+	if mmGet.defaultExpectation.params != nil {
+		mmGet.mock.t.Fatalf("UserRepositoryMock.Get mock is already set by Expect")
+	}
+
+	if mmGet.defaultExpectation.paramPtrs == nil {
+		mmGet.defaultExpectation.paramPtrs = &UserRepositoryMockGetParamPtrs{}
+	}
+	mmGet.defaultExpectation.paramPtrs.username = &username
+
+	return mmGet
+}
+
+// Inspect accepts an inspector function that has same arguments as the UserRepository.Get
+func (mmGet *mUserRepositoryMockGet) Inspect(f func(ctx context.Context, username string)) *mUserRepositoryMockGet {
+	if mmGet.mock.inspectFuncGet != nil {
+		mmGet.mock.t.Fatalf("Inspect function is already set for UserRepositoryMock.Get")
+	}
+
+	mmGet.mock.inspectFuncGet = f
+
+	return mmGet
+}
+
+// Return sets up results that will be returned by UserRepository.Get
+func (mmGet *mUserRepositoryMockGet) Return(up1 *models.User, err error) *UserRepositoryMock {
+	if mmGet.mock.funcGet != nil {
+		mmGet.mock.t.Fatalf("UserRepositoryMock.Get mock is already set by Set")
+	}
+
+	if mmGet.defaultExpectation == nil {
+		mmGet.defaultExpectation = &UserRepositoryMockGetExpectation{mock: mmGet.mock}
+	}
+	mmGet.defaultExpectation.results = &UserRepositoryMockGetResults{up1, err}
+	return mmGet.mock
+}
+
+// Set uses given function f to mock the UserRepository.Get method
+func (mmGet *mUserRepositoryMockGet) Set(f func(ctx context.Context, username string) (up1 *models.User, err error)) *UserRepositoryMock {
+	if mmGet.defaultExpectation != nil {
+		mmGet.mock.t.Fatalf("Default expectation is already set for the UserRepository.Get method")
+	}
+
+	if len(mmGet.expectations) > 0 {
+		mmGet.mock.t.Fatalf("Some expectations are already set for the UserRepository.Get method")
+	}
+
+	mmGet.mock.funcGet = f
+	return mmGet.mock
+}
+
+// When sets expectation for the UserRepository.Get which will trigger the result defined by the following
+// Then helper
+func (mmGet *mUserRepositoryMockGet) When(ctx context.Context, username string) *UserRepositoryMockGetExpectation {
+	if mmGet.mock.funcGet != nil {
+		mmGet.mock.t.Fatalf("UserRepositoryMock.Get mock is already set by Set")
+	}
+
+	expectation := &UserRepositoryMockGetExpectation{
+		mock:   mmGet.mock,
+		params: &UserRepositoryMockGetParams{ctx, username},
+	}
+	mmGet.expectations = append(mmGet.expectations, expectation)
+	return expectation
+}
+
+// Then sets up UserRepository.Get return parameters for the expectation previously defined by the When method
+func (e *UserRepositoryMockGetExpectation) Then(up1 *models.User, err error) *UserRepositoryMock {
+	e.results = &UserRepositoryMockGetResults{up1, err}
+	return e.mock
+}
+
+// Times sets number of times UserRepository.Get should be invoked
+func (mmGet *mUserRepositoryMockGet) Times(n uint64) *mUserRepositoryMockGet {
+	if n == 0 {
+		mmGet.mock.t.Fatalf("Times of UserRepositoryMock.Get mock can not be zero")
+	}
+	mm_atomic.StoreUint64(&mmGet.expectedInvocations, n)
+	return mmGet
+}
+
+func (mmGet *mUserRepositoryMockGet) invocationsDone() bool {
+	if len(mmGet.expectations) == 0 && mmGet.defaultExpectation == nil && mmGet.mock.funcGet == nil {
+		return true
+	}
+
+	totalInvocations := mm_atomic.LoadUint64(&mmGet.mock.afterGetCounter)
+	expectedInvocations := mm_atomic.LoadUint64(&mmGet.expectedInvocations)
+
+	return totalInvocations > 0 && (expectedInvocations == 0 || expectedInvocations == totalInvocations)
+}
+
+// Get implements auth.UserRepository
+func (mmGet *UserRepositoryMock) Get(ctx context.Context, username string) (up1 *models.User, err error) {
+	mm_atomic.AddUint64(&mmGet.beforeGetCounter, 1)
+	defer mm_atomic.AddUint64(&mmGet.afterGetCounter, 1)
+
+	if mmGet.inspectFuncGet != nil {
+		mmGet.inspectFuncGet(ctx, username)
+	}
+
+	mm_params := UserRepositoryMockGetParams{ctx, username}
+
+	// Record call args
+	mmGet.GetMock.mutex.Lock()
+	mmGet.GetMock.callArgs = append(mmGet.GetMock.callArgs, &mm_params)
+	mmGet.GetMock.mutex.Unlock()
+
+	for _, e := range mmGet.GetMock.expectations {
+		if minimock.Equal(*e.params, mm_params) {
+			mm_atomic.AddUint64(&e.Counter, 1)
+			return e.results.up1, e.results.err
+		}
+	}
+
+	if mmGet.GetMock.defaultExpectation != nil {
+		mm_atomic.AddUint64(&mmGet.GetMock.defaultExpectation.Counter, 1)
+		mm_want := mmGet.GetMock.defaultExpectation.params
+		mm_want_ptrs := mmGet.GetMock.defaultExpectation.paramPtrs
+
+		mm_got := UserRepositoryMockGetParams{ctx, username}
+
+		if mm_want_ptrs != nil {
+
+			if mm_want_ptrs.ctx != nil && !minimock.Equal(*mm_want_ptrs.ctx, mm_got.ctx) {
+				mmGet.t.Errorf("UserRepositoryMock.Get got unexpected parameter ctx, want: %#v, got: %#v%s\n", *mm_want_ptrs.ctx, mm_got.ctx, minimock.Diff(*mm_want_ptrs.ctx, mm_got.ctx))
+			}
+
+			if mm_want_ptrs.username != nil && !minimock.Equal(*mm_want_ptrs.username, mm_got.username) {
+				mmGet.t.Errorf("UserRepositoryMock.Get got unexpected parameter username, want: %#v, got: %#v%s\n", *mm_want_ptrs.username, mm_got.username, minimock.Diff(*mm_want_ptrs.username, mm_got.username))
+			}
+
+		} else if mm_want != nil && !minimock.Equal(*mm_want, mm_got) {
+			mmGet.t.Errorf("UserRepositoryMock.Get got unexpected parameters, want: %#v, got: %#v%s\n", *mm_want, mm_got, minimock.Diff(*mm_want, mm_got))
+		}
+
+		mm_results := mmGet.GetMock.defaultExpectation.results
+		if mm_results == nil {
+			mmGet.t.Fatal("No results are set for the UserRepositoryMock.Get")
+		}
+		return (*mm_results).up1, (*mm_results).err
+	}
+	if mmGet.funcGet != nil {
+		return mmGet.funcGet(ctx, username)
+	}
+	mmGet.t.Fatalf("Unexpected call to UserRepositoryMock.Get. %v %v", ctx, username)
+	return
+}
+
+// GetAfterCounter returns a count of finished UserRepositoryMock.Get invocations
+func (mmGet *UserRepositoryMock) GetAfterCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmGet.afterGetCounter)
+}
+
+// GetBeforeCounter returns a count of UserRepositoryMock.Get invocations
+func (mmGet *UserRepositoryMock) GetBeforeCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmGet.beforeGetCounter)
+}
+
+// Calls returns a list of arguments used in each call to UserRepositoryMock.Get.
+// The list is in the same order as the calls were made (i.e. recent calls have a higher index)
+func (mmGet *mUserRepositoryMockGet) Calls() []*UserRepositoryMockGetParams {
+	mmGet.mutex.RLock()
+
+	argCopy := make([]*UserRepositoryMockGetParams, len(mmGet.callArgs))
+	copy(argCopy, mmGet.callArgs)
+
+	mmGet.mutex.RUnlock()
+
+	return argCopy
+}
+
+// MinimockGetDone returns true if the count of the Get invocations corresponds
+// the number of defined expectations
+func (m *UserRepositoryMock) MinimockGetDone() bool {
+	if m.GetMock.optional {
+		// Optional methods provide '0 or more' call count restriction.
+		return true
+	}
+
+	for _, e := range m.GetMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			return false
+		}
+	}
+
+	return m.GetMock.invocationsDone()
+}
+
+// MinimockGetInspect logs each unmet expectation
+func (m *UserRepositoryMock) MinimockGetInspect() {
+	for _, e := range m.GetMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			m.t.Errorf("Expected call to UserRepositoryMock.Get with params: %#v", *e.params)
+		}
+	}
+
+	afterGetCounter := mm_atomic.LoadUint64(&m.afterGetCounter)
+	// if default expectation was set then invocations count should be greater than zero
+	if m.GetMock.defaultExpectation != nil && afterGetCounter < 1 {
+		if m.GetMock.defaultExpectation.params == nil {
+			m.t.Error("Expected call to UserRepositoryMock.Get")
+		} else {
+			m.t.Errorf("Expected call to UserRepositoryMock.Get with params: %#v", *m.GetMock.defaultExpectation.params)
+		}
+	}
+	// if func was set then invocations count should be greater than zero
+	if m.funcGet != nil && afterGetCounter < 1 {
+		m.t.Error("Expected call to UserRepositoryMock.Get")
+	}
+
+	if !m.GetMock.invocationsDone() && afterGetCounter > 0 {
+		m.t.Errorf("Expected %d calls to UserRepositoryMock.Get but found %d calls",
+			mm_atomic.LoadUint64(&m.GetMock.expectedInvocations), afterGetCounter)
+	}
+}
+
+// MinimockFinish checks that all mocked methods have been called the expected number of times
+func (m *UserRepositoryMock) MinimockFinish() {
+	m.finishOnce.Do(func() {
+		if !m.minimockDone() {
+			m.MinimockGetInspect()
+		}
+	})
+}
+
+// MinimockWait waits for all mocked methods to be called the expected number of times
+func (m *UserRepositoryMock) MinimockWait(timeout mm_time.Duration) {
+	timeoutCh := mm_time.After(timeout)
+	for {
+		if m.minimockDone() {
+			return
+		}
+		select {
+		case <-timeoutCh:
+			m.MinimockFinish()
+			return
+		case <-mm_time.After(10 * mm_time.Millisecond):
+		}
+	}
+}
+
+func (m *UserRepositoryMock) minimockDone() bool {
+	done := true
+	return done &&
+		m.MinimockGetDone()
+}

+ 46 - 10
internal/api/v1/image/add_image.go

@@ -1,22 +1,54 @@
 package image
 
+//go:generate mkdir -p mocks
+//go:generate rm -rf ./mocks/*_minimock.go
+//go:generate minimock -i FileRepository,ThingImageRepository,PlaceImageRepository -o ./mocks/ -s "_minimock.go"
+
 import (
+	"context"
 	"database/sql"
 	"mime/multipart"
 	"path/filepath"
 	"strconv"
 	"time"
 
+	"github.com/gofiber/fiber/v2"
+
 	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/factory"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/mappers"
-	"github.com/gofiber/fiber/v2"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
 )
 
 const fileDateLayout = "2006-01-02-15-04-05"
 
+type (
+	FileRepository interface {
+		Save(fctx *fiber.Ctx, header *multipart.FileHeader, path string) error
+		Delete(path string) error
+	}
+
+	ThingImageRepository interface {
+		Add(ctx context.Context, req models.AddThingImageRequest, tx *sql.Tx) error
+		Get(ctx context.Context, imageID int) (*models.Image, error)
+		GetByThingID(ctx context.Context, thingID int) ([]models.Image, error)
+		GetByPlaceID(ctx context.Context, placeID int) ([]models.Image, error)
+		Delete(ctx context.Context, imageID int, tx *sql.Tx) error
+		BeginTx(ctx context.Context, level sql.IsolationLevel) (*sql.Tx, error)
+		CommitTx(tx *sql.Tx) error
+	}
+
+	PlaceImageRepository interface {
+		Add(ctx context.Context, req models.AddPlaceImageRequest, tx *sql.Tx) error
+		Get(ctx context.Context, imageID int) (*models.Image, error)
+		GetByPlaceID(ctx context.Context, placeID int) ([]models.Image, error)
+		Delete(ctx context.Context, imageID int, tx *sql.Tx) error
+		BeginTx(ctx context.Context, level sql.IsolationLevel) (*sql.Tx, error)
+		CommitTx(tx *sql.Tx) error
+	}
+)
+
 // @Router 		/api/v1/images [post]
 // @Param       place_id formData int false "Place ID"
 // @Param       thing_id formData int false "Thing ID"
@@ -29,7 +61,11 @@ const fileDateLayout = "2006-01-02-15-04-05"
 // @security 	APIKey
 // @Accept      mpfd
 // @Produce     json
-func AddImageHandler(sp interfaces.ServiceProvider) fiber.Handler {
+func AddImageHandler(
+	fileRepository FileRepository,
+	thingImageRepository ThingImageRepository,
+	placeImageRepository PlaceImageRepository,
+) fiber.Handler {
 	return func(fctx *fiber.Ctx) error {
 		var form *multipart.Form
 		var placeID, thingID int
@@ -60,7 +96,7 @@ func AddImageHandler(sp interfaces.ServiceProvider) fiber.Handler {
 		for _, file := range form.File["files"] {
 			filename := "/files/" + date + "_" + helpers.GenerateRandomString(10) + filepath.Ext(file.Filename)
 
-			if err = sp.GetFileRepository().Save(fctx, file, filename); err != nil {
+			if err = fileRepository.Save(fctx, file, filename); err != nil {
 				return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 			}
 
@@ -73,33 +109,33 @@ func AddImageHandler(sp interfaces.ServiceProvider) fiber.Handler {
 
 		var tx *sql.Tx
 		if thingID > 0 {
-			tx, err = sp.GetThingImageRepository().BeginTx(ctx, API.DefaultTxLevel)
+			tx, err = thingImageRepository.BeginTx(ctx, API.DefaultTxLevel)
 			if err != nil {
 				return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 			}
 
 			for _, file := range files {
-				if err = sp.GetThingImageRepository().Add(ctx, mappers.ConvertToAddThingImageRequestModel(thingID, file), tx); err != nil {
+				if err = thingImageRepository.Add(ctx, mappers.ToAddThingImageRequest(thingID, file), tx); err != nil {
 					return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 				}
 			}
 
-			if err = sp.GetThingImageRepository().CommitTx(tx); err != nil {
+			if err = thingImageRepository.CommitTx(tx); err != nil {
 				return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 			}
 		} else {
-			tx, err = sp.GetPlaceImageRepository().BeginTx(ctx, API.DefaultTxLevel)
+			tx, err = placeImageRepository.BeginTx(ctx, API.DefaultTxLevel)
 			if err != nil {
 				return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 			}
 
 			for _, file := range files {
-				if err = sp.GetPlaceImageRepository().Add(ctx, mappers.ConvertToAddPlaceImageRequestModel(placeID, file), tx); err != nil {
+				if err = placeImageRepository.Add(ctx, mappers.ToAddPlaceImageRequest(placeID, file), tx); err != nil {
 					return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 				}
 			}
 
-			if err = sp.GetPlaceImageRepository().CommitTx(tx); err != nil {
+			if err = placeImageRepository.CommitTx(tx); err != nil {
 				return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 			}
 		}

+ 98 - 92
internal/api/v1/image/add_image_test.go

@@ -10,21 +10,22 @@ import (
 	"strconv"
 	"testing"
 
-	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
-	repoMocks "git.dmitriygnatenko.ru/dima/homethings/internal/repositories/mocks"
-	sp "git.dmitriygnatenko.ru/dima/homethings/internal/service_provider"
 	"github.com/brianvoe/gofakeit/v6"
 	"github.com/gofiber/fiber/v2"
 	"github.com/gojuno/minimock/v3"
 	"github.com/stretchr/testify/assert"
+
+	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/image/mocks"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
 )
 
 // nolint:errcheck
-func Test_AddImageHandler(t *testing.T) {
+func TestAddImageHandler(t *testing.T) {
+	t.Parallel()
+
 	type req struct {
 		method      string
 		route       string
@@ -33,7 +34,6 @@ func Test_AddImageHandler(t *testing.T) {
 	}
 
 	var (
-		mc        = minimock.NewController(t)
 		placeID   = gofakeit.Number(1, 1000)
 		thingID   = gofakeit.Number(1, 1000)
 		testError = errors.New(gofakeit.Phrase())
@@ -80,9 +80,9 @@ func Test_AddImageHandler(t *testing.T) {
 		req                req
 		resCode            int
 		resBody            interface{}
-		fileRepoMock       func(mc *minimock.Controller) interfaces.FileRepository
-		placeImageRepoMock func(mc *minimock.Controller) interfaces.PlaceImageRepository
-		thingImageRepoMock func(mc *minimock.Controller) interfaces.ThingImageRepository
+		fileRepoMock       func(mc *minimock.Controller) FileRepository
+		placeImageRepoMock func(mc *minimock.Controller) PlaceImageRepository
+		thingImageRepoMock func(mc *minimock.Controller) ThingImageRepository
 	}{
 		{
 			name: "negative case - bad request",
@@ -91,14 +91,14 @@ func Test_AddImageHandler(t *testing.T) {
 				route:  "/v1/images",
 			},
 			resCode: fiber.StatusBadRequest,
-			placeImageRepoMock: func(mc *minimock.Controller) interfaces.PlaceImageRepository {
-				return repoMocks.NewPlaceImageRepositoryMock(mc)
+			placeImageRepoMock: func(mc *minimock.Controller) PlaceImageRepository {
+				return mocks.NewPlaceImageRepositoryMock(mc)
 			},
-			thingImageRepoMock: func(mc *minimock.Controller) interfaces.ThingImageRepository {
-				return repoMocks.NewThingImageRepositoryMock(mc)
+			thingImageRepoMock: func(mc *minimock.Controller) ThingImageRepository {
+				return mocks.NewThingImageRepositoryMock(mc)
 			},
-			fileRepoMock: func(mc *minimock.Controller) interfaces.FileRepository {
-				return repoMocks.NewFileRepositoryMock(mc)
+			fileRepoMock: func(mc *minimock.Controller) FileRepository {
+				return mocks.NewFileRepositoryMock(mc)
 			},
 		},
 		{
@@ -110,14 +110,14 @@ func Test_AddImageHandler(t *testing.T) {
 				contentType: addPlaceIncorrectContentType,
 			},
 			resCode: fiber.StatusBadRequest,
-			placeImageRepoMock: func(mc *minimock.Controller) interfaces.PlaceImageRepository {
-				return repoMocks.NewPlaceImageRepositoryMock(mc)
+			placeImageRepoMock: func(mc *minimock.Controller) PlaceImageRepository {
+				return mocks.NewPlaceImageRepositoryMock(mc)
 			},
-			thingImageRepoMock: func(mc *minimock.Controller) interfaces.ThingImageRepository {
-				return repoMocks.NewThingImageRepositoryMock(mc)
+			thingImageRepoMock: func(mc *minimock.Controller) ThingImageRepository {
+				return mocks.NewThingImageRepositoryMock(mc)
 			},
-			fileRepoMock: func(mc *minimock.Controller) interfaces.FileRepository {
-				return repoMocks.NewFileRepositoryMock(mc)
+			fileRepoMock: func(mc *minimock.Controller) FileRepository {
+				return mocks.NewFileRepositoryMock(mc)
 			},
 		},
 		{
@@ -129,14 +129,14 @@ func Test_AddImageHandler(t *testing.T) {
 				contentType: addThingIncorrectContentType,
 			},
 			resCode: fiber.StatusBadRequest,
-			placeImageRepoMock: func(mc *minimock.Controller) interfaces.PlaceImageRepository {
-				return repoMocks.NewPlaceImageRepositoryMock(mc)
+			placeImageRepoMock: func(mc *minimock.Controller) PlaceImageRepository {
+				return mocks.NewPlaceImageRepositoryMock(mc)
 			},
-			thingImageRepoMock: func(mc *minimock.Controller) interfaces.ThingImageRepository {
-				return repoMocks.NewThingImageRepositoryMock(mc)
+			thingImageRepoMock: func(mc *minimock.Controller) ThingImageRepository {
+				return mocks.NewThingImageRepositoryMock(mc)
 			},
-			fileRepoMock: func(mc *minimock.Controller) interfaces.FileRepository {
-				return repoMocks.NewFileRepositoryMock(mc)
+			fileRepoMock: func(mc *minimock.Controller) FileRepository {
+				return mocks.NewFileRepositoryMock(mc)
 			},
 		},
 		{
@@ -148,14 +148,14 @@ func Test_AddImageHandler(t *testing.T) {
 				contentType: emptyContentType,
 			},
 			resCode: fiber.StatusBadRequest,
-			placeImageRepoMock: func(mc *minimock.Controller) interfaces.PlaceImageRepository {
-				return repoMocks.NewPlaceImageRepositoryMock(mc)
+			placeImageRepoMock: func(mc *minimock.Controller) PlaceImageRepository {
+				return mocks.NewPlaceImageRepositoryMock(mc)
 			},
-			thingImageRepoMock: func(mc *minimock.Controller) interfaces.ThingImageRepository {
-				return repoMocks.NewThingImageRepositoryMock(mc)
+			thingImageRepoMock: func(mc *minimock.Controller) ThingImageRepository {
+				return mocks.NewThingImageRepositoryMock(mc)
 			},
-			fileRepoMock: func(mc *minimock.Controller) interfaces.FileRepository {
-				return repoMocks.NewFileRepositoryMock(mc)
+			fileRepoMock: func(mc *minimock.Controller) FileRepository {
+				return mocks.NewFileRepositoryMock(mc)
 			},
 		},
 		{
@@ -167,16 +167,16 @@ func Test_AddImageHandler(t *testing.T) {
 				contentType: addPlaceCorrectContentType,
 			},
 			resCode: fiber.StatusInternalServerError,
-			placeImageRepoMock: func(mc *minimock.Controller) interfaces.PlaceImageRepository {
-				mock := repoMocks.NewPlaceImageRepositoryMock(mc)
+			placeImageRepoMock: func(mc *minimock.Controller) PlaceImageRepository {
+				mock := mocks.NewPlaceImageRepositoryMock(mc)
 				mock.BeginTxMock.Return(nil, testError)
 				return mock
 			},
-			thingImageRepoMock: func(mc *minimock.Controller) interfaces.ThingImageRepository {
-				return repoMocks.NewThingImageRepositoryMock(mc)
+			thingImageRepoMock: func(mc *minimock.Controller) ThingImageRepository {
+				return mocks.NewThingImageRepositoryMock(mc)
 			},
-			fileRepoMock: func(mc *minimock.Controller) interfaces.FileRepository {
-				mock := repoMocks.NewFileRepositoryMock(mc)
+			fileRepoMock: func(mc *minimock.Controller) FileRepository {
+				mock := mocks.NewFileRepositoryMock(mc)
 				mock.SaveMock.Return(nil)
 				return mock
 			},
@@ -190,8 +190,8 @@ func Test_AddImageHandler(t *testing.T) {
 				contentType: addPlaceCorrectContentType,
 			},
 			resCode: fiber.StatusInternalServerError,
-			placeImageRepoMock: func(mc *minimock.Controller) interfaces.PlaceImageRepository {
-				mock := repoMocks.NewPlaceImageRepositoryMock(mc)
+			placeImageRepoMock: func(mc *minimock.Controller) PlaceImageRepository {
+				mock := mocks.NewPlaceImageRepositoryMock(mc)
 
 				mock.BeginTxMock.Return(nil, nil)
 
@@ -203,11 +203,11 @@ func Test_AddImageHandler(t *testing.T) {
 
 				return mock
 			},
-			thingImageRepoMock: func(mc *minimock.Controller) interfaces.ThingImageRepository {
-				return repoMocks.NewThingImageRepositoryMock(mc)
+			thingImageRepoMock: func(mc *minimock.Controller) ThingImageRepository {
+				return mocks.NewThingImageRepositoryMock(mc)
 			},
-			fileRepoMock: func(mc *minimock.Controller) interfaces.FileRepository {
-				mock := repoMocks.NewFileRepositoryMock(mc)
+			fileRepoMock: func(mc *minimock.Controller) FileRepository {
+				mock := mocks.NewFileRepositoryMock(mc)
 				mock.SaveMock.Return(nil)
 				return mock
 			},
@@ -221,8 +221,8 @@ func Test_AddImageHandler(t *testing.T) {
 				contentType: addPlaceCorrectContentType,
 			},
 			resCode: fiber.StatusInternalServerError,
-			placeImageRepoMock: func(mc *minimock.Controller) interfaces.PlaceImageRepository {
-				mock := repoMocks.NewPlaceImageRepositoryMock(mc)
+			placeImageRepoMock: func(mc *minimock.Controller) PlaceImageRepository {
+				mock := mocks.NewPlaceImageRepositoryMock(mc)
 
 				mock.BeginTxMock.Return(nil, nil)
 
@@ -232,11 +232,11 @@ func Test_AddImageHandler(t *testing.T) {
 
 				return mock
 			},
-			thingImageRepoMock: func(mc *minimock.Controller) interfaces.ThingImageRepository {
-				return repoMocks.NewThingImageRepositoryMock(mc)
+			thingImageRepoMock: func(mc *minimock.Controller) ThingImageRepository {
+				return mocks.NewThingImageRepositoryMock(mc)
 			},
-			fileRepoMock: func(mc *minimock.Controller) interfaces.FileRepository {
-				mock := repoMocks.NewFileRepositoryMock(mc)
+			fileRepoMock: func(mc *minimock.Controller) FileRepository {
+				mock := mocks.NewFileRepositoryMock(mc)
 				mock.SaveMock.Return(nil)
 				return mock
 			},
@@ -251,8 +251,8 @@ func Test_AddImageHandler(t *testing.T) {
 			},
 			resCode: fiber.StatusOK,
 			resBody: dto.EmptyResponse{},
-			placeImageRepoMock: func(mc *minimock.Controller) interfaces.PlaceImageRepository {
-				mock := repoMocks.NewPlaceImageRepositoryMock(mc)
+			placeImageRepoMock: func(mc *minimock.Controller) PlaceImageRepository {
+				mock := mocks.NewPlaceImageRepositoryMock(mc)
 
 				mock.BeginTxMock.Return(nil, nil)
 
@@ -264,11 +264,11 @@ func Test_AddImageHandler(t *testing.T) {
 
 				return mock
 			},
-			thingImageRepoMock: func(mc *minimock.Controller) interfaces.ThingImageRepository {
-				return repoMocks.NewThingImageRepositoryMock(mc)
+			thingImageRepoMock: func(mc *minimock.Controller) ThingImageRepository {
+				return mocks.NewThingImageRepositoryMock(mc)
 			},
-			fileRepoMock: func(mc *minimock.Controller) interfaces.FileRepository {
-				mock := repoMocks.NewFileRepositoryMock(mc)
+			fileRepoMock: func(mc *minimock.Controller) FileRepository {
+				mock := mocks.NewFileRepositoryMock(mc)
 				mock.SaveMock.Return(nil)
 				return mock
 			},
@@ -282,16 +282,16 @@ func Test_AddImageHandler(t *testing.T) {
 				contentType: addThingCorrectContentType,
 			},
 			resCode: fiber.StatusInternalServerError,
-			placeImageRepoMock: func(mc *minimock.Controller) interfaces.PlaceImageRepository {
-				return repoMocks.NewPlaceImageRepositoryMock(mc)
+			placeImageRepoMock: func(mc *minimock.Controller) PlaceImageRepository {
+				return mocks.NewPlaceImageRepositoryMock(mc)
 			},
-			thingImageRepoMock: func(mc *minimock.Controller) interfaces.ThingImageRepository {
-				mock := repoMocks.NewThingImageRepositoryMock(mc)
+			thingImageRepoMock: func(mc *minimock.Controller) ThingImageRepository {
+				mock := mocks.NewThingImageRepositoryMock(mc)
 				mock.BeginTxMock.Return(nil, testError)
 				return mock
 			},
-			fileRepoMock: func(mc *minimock.Controller) interfaces.FileRepository {
-				mock := repoMocks.NewFileRepositoryMock(mc)
+			fileRepoMock: func(mc *minimock.Controller) FileRepository {
+				mock := mocks.NewFileRepositoryMock(mc)
 				mock.SaveMock.Return(nil)
 				return mock
 			},
@@ -305,11 +305,11 @@ func Test_AddImageHandler(t *testing.T) {
 				contentType: addThingCorrectContentType,
 			},
 			resCode: fiber.StatusInternalServerError,
-			placeImageRepoMock: func(mc *minimock.Controller) interfaces.PlaceImageRepository {
-				return repoMocks.NewPlaceImageRepositoryMock(mc)
+			placeImageRepoMock: func(mc *minimock.Controller) PlaceImageRepository {
+				return mocks.NewPlaceImageRepositoryMock(mc)
 			},
-			thingImageRepoMock: func(mc *minimock.Controller) interfaces.ThingImageRepository {
-				mock := repoMocks.NewThingImageRepositoryMock(mc)
+			thingImageRepoMock: func(mc *minimock.Controller) ThingImageRepository {
+				mock := mocks.NewThingImageRepositoryMock(mc)
 
 				mock.BeginTxMock.Return(nil, nil)
 
@@ -321,8 +321,8 @@ func Test_AddImageHandler(t *testing.T) {
 
 				return mock
 			},
-			fileRepoMock: func(mc *minimock.Controller) interfaces.FileRepository {
-				mock := repoMocks.NewFileRepositoryMock(mc)
+			fileRepoMock: func(mc *minimock.Controller) FileRepository {
+				mock := mocks.NewFileRepositoryMock(mc)
 				mock.SaveMock.Return(nil)
 				return mock
 			},
@@ -336,11 +336,11 @@ func Test_AddImageHandler(t *testing.T) {
 				contentType: addThingCorrectContentType,
 			},
 			resCode: fiber.StatusInternalServerError,
-			placeImageRepoMock: func(mc *minimock.Controller) interfaces.PlaceImageRepository {
-				return repoMocks.NewPlaceImageRepositoryMock(mc)
+			placeImageRepoMock: func(mc *minimock.Controller) PlaceImageRepository {
+				return mocks.NewPlaceImageRepositoryMock(mc)
 			},
-			thingImageRepoMock: func(mc *minimock.Controller) interfaces.ThingImageRepository {
-				mock := repoMocks.NewThingImageRepositoryMock(mc)
+			thingImageRepoMock: func(mc *minimock.Controller) ThingImageRepository {
+				mock := mocks.NewThingImageRepositoryMock(mc)
 
 				mock.BeginTxMock.Return(nil, nil)
 
@@ -350,8 +350,8 @@ func Test_AddImageHandler(t *testing.T) {
 
 				return mock
 			},
-			fileRepoMock: func(mc *minimock.Controller) interfaces.FileRepository {
-				mock := repoMocks.NewFileRepositoryMock(mc)
+			fileRepoMock: func(mc *minimock.Controller) FileRepository {
+				mock := mocks.NewFileRepositoryMock(mc)
 				mock.SaveMock.Return(nil)
 				return mock
 			},
@@ -366,11 +366,11 @@ func Test_AddImageHandler(t *testing.T) {
 			},
 			resCode: fiber.StatusOK,
 			resBody: dto.EmptyResponse{},
-			placeImageRepoMock: func(mc *minimock.Controller) interfaces.PlaceImageRepository {
-				return repoMocks.NewPlaceImageRepositoryMock(mc)
+			placeImageRepoMock: func(mc *minimock.Controller) PlaceImageRepository {
+				return mocks.NewPlaceImageRepositoryMock(mc)
 			},
-			thingImageRepoMock: func(mc *minimock.Controller) interfaces.ThingImageRepository {
-				mock := repoMocks.NewThingImageRepositoryMock(mc)
+			thingImageRepoMock: func(mc *minimock.Controller) ThingImageRepository {
+				mock := mocks.NewThingImageRepositoryMock(mc)
 
 				mock.BeginTxMock.Return(nil, nil)
 
@@ -382,8 +382,8 @@ func Test_AddImageHandler(t *testing.T) {
 
 				return mock
 			},
-			fileRepoMock: func(mc *minimock.Controller) interfaces.FileRepository {
-				mock := repoMocks.NewFileRepositoryMock(mc)
+			fileRepoMock: func(mc *minimock.Controller) FileRepository {
+				mock := mocks.NewFileRepositoryMock(mc)
 				mock.SaveMock.Return(nil)
 				return mock
 			},
@@ -397,14 +397,14 @@ func Test_AddImageHandler(t *testing.T) {
 				contentType: addThingCorrectContentType,
 			},
 			resCode: fiber.StatusInternalServerError,
-			placeImageRepoMock: func(mc *minimock.Controller) interfaces.PlaceImageRepository {
-				return repoMocks.NewPlaceImageRepositoryMock(mc)
+			placeImageRepoMock: func(mc *minimock.Controller) PlaceImageRepository {
+				return mocks.NewPlaceImageRepositoryMock(mc)
 			},
-			thingImageRepoMock: func(mc *minimock.Controller) interfaces.ThingImageRepository {
-				return repoMocks.NewThingImageRepositoryMock(mc)
+			thingImageRepoMock: func(mc *minimock.Controller) ThingImageRepository {
+				return mocks.NewThingImageRepositoryMock(mc)
 			},
-			fileRepoMock: func(mc *minimock.Controller) interfaces.FileRepository {
-				mock := repoMocks.NewFileRepositoryMock(mc)
+			fileRepoMock: func(mc *minimock.Controller) FileRepository {
+				mock := mocks.NewFileRepositoryMock(mc)
 				mock.SaveMock.Return(testError)
 				return mock
 			},
@@ -413,10 +413,16 @@ func Test_AddImageHandler(t *testing.T) {
 
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
+			t.Parallel()
+
+			mc := minimock.NewController(t)
 			fiberApp := fiber.New()
-			serviceProvider := sp.InitMock(tt.placeImageRepoMock(mc), tt.thingImageRepoMock(mc), tt.fileRepoMock(mc))
 
-			fiberApp.Post("/v1/images", AddImageHandler(serviceProvider))
+			fiberApp.Post("/v1/images", AddImageHandler(
+				tt.fileRepoMock(mc),
+				tt.thingImageRepoMock(mc),
+				tt.placeImageRepoMock(mc),
+			))
 
 			fiberReq := httptest.NewRequest(tt.req.method, tt.req.route, bytes.NewReader(tt.req.body))
 			fiberReq.Header.Add(fiber.HeaderContentType, tt.req.contentType)

+ 11 - 7
internal/api/v1/image/delete_place_image.go

@@ -2,10 +2,11 @@ package image
 
 import (
 	"database/sql"
+	"errors"
 
-	"git.dmitriygnatenko.ru/dima/homethings/internal/factory"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
 	"github.com/gofiber/fiber/v2"
+
+	"git.dmitriygnatenko.ru/dima/homethings/internal/factory"
 )
 
 // @Router 		/api/v1/images/place/{imageId} [delete]
@@ -18,7 +19,10 @@ import (
 // @security 	APIKey
 // @Accept      json
 // @Produce     json
-func DeletePlaceImageHandler(sp interfaces.ServiceProvider) fiber.Handler {
+func DeletePlaceImageHandler(
+	fileRepository FileRepository,
+	placeImageRepository PlaceImageRepository,
+) fiber.Handler {
 	return func(fctx *fiber.Ctx) error {
 		ctx := fctx.Context()
 		id, err := fctx.ParamsInt("imageId")
@@ -26,20 +30,20 @@ func DeletePlaceImageHandler(sp interfaces.ServiceProvider) fiber.Handler {
 			return fiber.NewError(fiber.StatusBadRequest, err.Error())
 		}
 
-		image, err := sp.GetPlaceImageRepository().Get(ctx, id)
+		image, err := placeImageRepository.Get(ctx, id)
 		if err != nil {
-			if err == sql.ErrNoRows {
+			if errors.Is(err, sql.ErrNoRows) {
 				return fiber.NewError(fiber.StatusBadRequest, "")
 			}
 
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
-		if err = sp.GetPlaceImageRepository().Delete(ctx, id, nil); err != nil {
+		if err = placeImageRepository.Delete(ctx, id, nil); err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
-		if err = sp.GetFileRepository().Delete(image.Image); err != nil {
+		if err = fileRepository.Delete(image.Image); err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 

+ 42 - 37
internal/api/v1/image/delete_place_image_test.go

@@ -8,27 +8,27 @@ import (
 	"strconv"
 	"testing"
 
-	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
-	repoMocks "git.dmitriygnatenko.ru/dima/homethings/internal/repositories/mocks"
-	sp "git.dmitriygnatenko.ru/dima/homethings/internal/service_provider"
 	"github.com/brianvoe/gofakeit/v6"
 	"github.com/gofiber/fiber/v2"
 	"github.com/gojuno/minimock/v3"
 	"github.com/stretchr/testify/assert"
+
+	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/image/mocks"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
 )
 
-func Test_DeletePlaceImageHandler(t *testing.T) {
+func TestDeletePlaceImageHandler(t *testing.T) {
+	t.Parallel()
+
 	type req struct {
 		method string
 		route  string
 	}
 
 	var (
-		mc        = minimock.NewController(t)
 		imageID   = gofakeit.Number(1, 1000)
 		imageURL  = gofakeit.URL()
 		testError = errors.New(gofakeit.Phrase())
@@ -48,8 +48,8 @@ func Test_DeletePlaceImageHandler(t *testing.T) {
 		req                req
 		resCode            int
 		resBody            interface{}
-		placeImageRepoMock func(mc *minimock.Controller) interfaces.PlaceImageRepository
-		fileRepoMock       func(mc *minimock.Controller) interfaces.FileRepository
+		placeImageRepoMock func(mc *minimock.Controller) PlaceImageRepository
+		fileRepoMock       func(mc *minimock.Controller) FileRepository
 	}{
 		{
 			name: "negative case - bad request",
@@ -58,19 +58,19 @@ func Test_DeletePlaceImageHandler(t *testing.T) {
 				route:  "/v1/images/place/" + gofakeit.Word(),
 			},
 			resCode: fiber.StatusBadRequest,
-			placeImageRepoMock: func(mc *minimock.Controller) interfaces.PlaceImageRepository {
-				return repoMocks.NewPlaceImageRepositoryMock(mc)
+			placeImageRepoMock: func(mc *minimock.Controller) PlaceImageRepository {
+				return mocks.NewPlaceImageRepositoryMock(mc)
 			},
-			fileRepoMock: func(mc *minimock.Controller) interfaces.FileRepository {
-				return repoMocks.NewFileRepositoryMock(mc)
+			fileRepoMock: func(mc *minimock.Controller) FileRepository {
+				return mocks.NewFileRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - bad request (image not exists)",
 			req:     correctReq,
 			resCode: fiber.StatusBadRequest,
-			placeImageRepoMock: func(mc *minimock.Controller) interfaces.PlaceImageRepository {
-				mock := repoMocks.NewPlaceImageRepositoryMock(mc)
+			placeImageRepoMock: func(mc *minimock.Controller) PlaceImageRepository {
+				mock := mocks.NewPlaceImageRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, imageID, id)
@@ -78,16 +78,16 @@ func Test_DeletePlaceImageHandler(t *testing.T) {
 
 				return mock
 			},
-			fileRepoMock: func(mc *minimock.Controller) interfaces.FileRepository {
-				return repoMocks.NewFileRepositoryMock(mc)
+			fileRepoMock: func(mc *minimock.Controller) FileRepository {
+				return mocks.NewFileRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - repository error (get)",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			placeImageRepoMock: func(mc *minimock.Controller) interfaces.PlaceImageRepository {
-				mock := repoMocks.NewPlaceImageRepositoryMock(mc)
+			placeImageRepoMock: func(mc *minimock.Controller) PlaceImageRepository {
+				mock := mocks.NewPlaceImageRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, imageID, id)
@@ -95,16 +95,16 @@ func Test_DeletePlaceImageHandler(t *testing.T) {
 
 				return mock
 			},
-			fileRepoMock: func(mc *minimock.Controller) interfaces.FileRepository {
-				return repoMocks.NewFileRepositoryMock(mc)
+			fileRepoMock: func(mc *minimock.Controller) FileRepository {
+				return mocks.NewFileRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - repository error (update)",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			placeImageRepoMock: func(mc *minimock.Controller) interfaces.PlaceImageRepository {
-				mock := repoMocks.NewPlaceImageRepositoryMock(mc)
+			placeImageRepoMock: func(mc *minimock.Controller) PlaceImageRepository {
+				mock := mocks.NewPlaceImageRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, imageID, id)
@@ -116,16 +116,16 @@ func Test_DeletePlaceImageHandler(t *testing.T) {
 
 				return mock
 			},
-			fileRepoMock: func(mc *minimock.Controller) interfaces.FileRepository {
-				return repoMocks.NewFileRepositoryMock(mc)
+			fileRepoMock: func(mc *minimock.Controller) FileRepository {
+				return mocks.NewFileRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - file delete error",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			placeImageRepoMock: func(mc *minimock.Controller) interfaces.PlaceImageRepository {
-				mock := repoMocks.NewPlaceImageRepositoryMock(mc)
+			placeImageRepoMock: func(mc *minimock.Controller) PlaceImageRepository {
+				mock := mocks.NewPlaceImageRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, imageID, id)
@@ -137,8 +137,8 @@ func Test_DeletePlaceImageHandler(t *testing.T) {
 
 				return mock
 			},
-			fileRepoMock: func(mc *minimock.Controller) interfaces.FileRepository {
-				mock := repoMocks.NewFileRepositoryMock(mc)
+			fileRepoMock: func(mc *minimock.Controller) FileRepository {
+				mock := mocks.NewFileRepositoryMock(mc)
 				mock.DeleteMock.Return(testError)
 				return mock
 			},
@@ -148,8 +148,8 @@ func Test_DeletePlaceImageHandler(t *testing.T) {
 			req:     correctReq,
 			resCode: fiber.StatusOK,
 			resBody: dto.EmptyResponse{},
-			placeImageRepoMock: func(mc *minimock.Controller) interfaces.PlaceImageRepository {
-				mock := repoMocks.NewPlaceImageRepositoryMock(mc)
+			placeImageRepoMock: func(mc *minimock.Controller) PlaceImageRepository {
+				mock := mocks.NewPlaceImageRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, imageID, id)
@@ -161,8 +161,8 @@ func Test_DeletePlaceImageHandler(t *testing.T) {
 
 				return mock
 			},
-			fileRepoMock: func(mc *minimock.Controller) interfaces.FileRepository {
-				mock := repoMocks.NewFileRepositoryMock(mc)
+			fileRepoMock: func(mc *minimock.Controller) FileRepository {
+				mock := mocks.NewFileRepositoryMock(mc)
 				mock.DeleteMock.Return(nil)
 				return mock
 			},
@@ -171,10 +171,15 @@ func Test_DeletePlaceImageHandler(t *testing.T) {
 
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
+			t.Parallel()
+
+			mc := minimock.NewController(t)
 			fiberApp := fiber.New()
-			serviceProvider := sp.InitMock(tt.placeImageRepoMock(mc), tt.fileRepoMock(mc))
 
-			fiberApp.Delete("/v1/images/place/:imageId", DeletePlaceImageHandler(serviceProvider))
+			fiberApp.Delete("/v1/images/place/:imageId", DeletePlaceImageHandler(
+				tt.fileRepoMock(mc),
+				tt.placeImageRepoMock(mc),
+			))
 
 			fiberRes, _ := fiberApp.Test(httptest.NewRequest(tt.req.method, tt.req.route, nil), API.DefaultTestTimeOut)
 

+ 11 - 7
internal/api/v1/image/delete_thing_image.go

@@ -2,10 +2,11 @@ package image
 
 import (
 	"database/sql"
+	"errors"
 
-	"git.dmitriygnatenko.ru/dima/homethings/internal/factory"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
 	"github.com/gofiber/fiber/v2"
+
+	"git.dmitriygnatenko.ru/dima/homethings/internal/factory"
 )
 
 // @Router 		/api/v1/images/thing/{imageId} [delete]
@@ -18,7 +19,10 @@ import (
 // @security 	APIKey
 // @Accept      json
 // @Produce     json
-func DeleteThingImageHandler(sp interfaces.ServiceProvider) fiber.Handler {
+func DeleteThingImageHandler(
+	fileRepository FileRepository,
+	thingImageRepository ThingImageRepository,
+) fiber.Handler {
 	return func(fctx *fiber.Ctx) error {
 		ctx := fctx.Context()
 		id, err := fctx.ParamsInt("imageId")
@@ -26,20 +30,20 @@ func DeleteThingImageHandler(sp interfaces.ServiceProvider) fiber.Handler {
 			return fiber.NewError(fiber.StatusBadRequest, err.Error())
 		}
 
-		image, err := sp.GetThingImageRepository().Get(ctx, id)
+		image, err := thingImageRepository.Get(ctx, id)
 		if err != nil {
-			if err == sql.ErrNoRows {
+			if errors.Is(err, sql.ErrNoRows) {
 				return fiber.NewError(fiber.StatusBadRequest, "")
 			}
 
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
-		if err = sp.GetThingImageRepository().Delete(ctx, id, nil); err != nil {
+		if err = thingImageRepository.Delete(ctx, id, nil); err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
-		if err = sp.GetFileRepository().Delete(image.Image); err != nil {
+		if err = fileRepository.Delete(image.Image); err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 

+ 42 - 37
internal/api/v1/image/delete_thing_image_test.go

@@ -8,27 +8,27 @@ import (
 	"strconv"
 	"testing"
 
-	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
-	repoMocks "git.dmitriygnatenko.ru/dima/homethings/internal/repositories/mocks"
-	sp "git.dmitriygnatenko.ru/dima/homethings/internal/service_provider"
 	"github.com/brianvoe/gofakeit/v6"
 	"github.com/gofiber/fiber/v2"
 	"github.com/gojuno/minimock/v3"
 	"github.com/stretchr/testify/assert"
+
+	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/image/mocks"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
 )
 
-func Test_DeleteThingImageHandler(t *testing.T) {
+func TestDeleteThingImageHandler(t *testing.T) {
+	t.Parallel()
+
 	type req struct {
 		method string
 		route  string
 	}
 
 	var (
-		mc        = minimock.NewController(t)
 		imageID   = gofakeit.Number(1, 1000)
 		imageURL  = gofakeit.URL()
 		testError = errors.New(gofakeit.Phrase())
@@ -48,8 +48,8 @@ func Test_DeleteThingImageHandler(t *testing.T) {
 		req                req
 		resCode            int
 		resBody            interface{}
-		thingImageRepoMock func(mc *minimock.Controller) interfaces.ThingImageRepository
-		fileRepoMock       func(mc *minimock.Controller) interfaces.FileRepository
+		thingImageRepoMock func(mc *minimock.Controller) ThingImageRepository
+		fileRepoMock       func(mc *minimock.Controller) FileRepository
 	}{
 		{
 			name: "negative case - bad request",
@@ -58,19 +58,19 @@ func Test_DeleteThingImageHandler(t *testing.T) {
 				route:  "/v1/images/thing/" + gofakeit.Word(),
 			},
 			resCode: fiber.StatusBadRequest,
-			thingImageRepoMock: func(mc *minimock.Controller) interfaces.ThingImageRepository {
-				return repoMocks.NewThingImageRepositoryMock(mc)
+			thingImageRepoMock: func(mc *minimock.Controller) ThingImageRepository {
+				return mocks.NewThingImageRepositoryMock(mc)
 			},
-			fileRepoMock: func(mc *minimock.Controller) interfaces.FileRepository {
-				return repoMocks.NewFileRepositoryMock(mc)
+			fileRepoMock: func(mc *minimock.Controller) FileRepository {
+				return mocks.NewFileRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - bad request (image not exists)",
 			req:     correctReq,
 			resCode: fiber.StatusBadRequest,
-			thingImageRepoMock: func(mc *minimock.Controller) interfaces.ThingImageRepository {
-				mock := repoMocks.NewThingImageRepositoryMock(mc)
+			thingImageRepoMock: func(mc *minimock.Controller) ThingImageRepository {
+				mock := mocks.NewThingImageRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, imageID, id)
@@ -78,16 +78,16 @@ func Test_DeleteThingImageHandler(t *testing.T) {
 
 				return mock
 			},
-			fileRepoMock: func(mc *minimock.Controller) interfaces.FileRepository {
-				return repoMocks.NewFileRepositoryMock(mc)
+			fileRepoMock: func(mc *minimock.Controller) FileRepository {
+				return mocks.NewFileRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - repository error (get)",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			thingImageRepoMock: func(mc *minimock.Controller) interfaces.ThingImageRepository {
-				mock := repoMocks.NewThingImageRepositoryMock(mc)
+			thingImageRepoMock: func(mc *minimock.Controller) ThingImageRepository {
+				mock := mocks.NewThingImageRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, imageID, id)
@@ -95,16 +95,16 @@ func Test_DeleteThingImageHandler(t *testing.T) {
 
 				return mock
 			},
-			fileRepoMock: func(mc *minimock.Controller) interfaces.FileRepository {
-				return repoMocks.NewFileRepositoryMock(mc)
+			fileRepoMock: func(mc *minimock.Controller) FileRepository {
+				return mocks.NewFileRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - repository error (delete)",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			thingImageRepoMock: func(mc *minimock.Controller) interfaces.ThingImageRepository {
-				mock := repoMocks.NewThingImageRepositoryMock(mc)
+			thingImageRepoMock: func(mc *minimock.Controller) ThingImageRepository {
+				mock := mocks.NewThingImageRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, imageID, id)
@@ -116,16 +116,16 @@ func Test_DeleteThingImageHandler(t *testing.T) {
 
 				return mock
 			},
-			fileRepoMock: func(mc *minimock.Controller) interfaces.FileRepository {
-				return repoMocks.NewFileRepositoryMock(mc)
+			fileRepoMock: func(mc *minimock.Controller) FileRepository {
+				return mocks.NewFileRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - file delete error",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			thingImageRepoMock: func(mc *minimock.Controller) interfaces.ThingImageRepository {
-				mock := repoMocks.NewThingImageRepositoryMock(mc)
+			thingImageRepoMock: func(mc *minimock.Controller) ThingImageRepository {
+				mock := mocks.NewThingImageRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, imageID, id)
@@ -137,8 +137,8 @@ func Test_DeleteThingImageHandler(t *testing.T) {
 
 				return mock
 			},
-			fileRepoMock: func(mc *minimock.Controller) interfaces.FileRepository {
-				mock := repoMocks.NewFileRepositoryMock(mc)
+			fileRepoMock: func(mc *minimock.Controller) FileRepository {
+				mock := mocks.NewFileRepositoryMock(mc)
 				mock.DeleteMock.Return(testError)
 				return mock
 			},
@@ -148,8 +148,8 @@ func Test_DeleteThingImageHandler(t *testing.T) {
 			req:     correctReq,
 			resCode: fiber.StatusOK,
 			resBody: dto.EmptyResponse{},
-			thingImageRepoMock: func(mc *minimock.Controller) interfaces.ThingImageRepository {
-				mock := repoMocks.NewThingImageRepositoryMock(mc)
+			thingImageRepoMock: func(mc *minimock.Controller) ThingImageRepository {
+				mock := mocks.NewThingImageRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, imageID, id)
@@ -161,8 +161,8 @@ func Test_DeleteThingImageHandler(t *testing.T) {
 
 				return mock
 			},
-			fileRepoMock: func(mc *minimock.Controller) interfaces.FileRepository {
-				mock := repoMocks.NewFileRepositoryMock(mc)
+			fileRepoMock: func(mc *minimock.Controller) FileRepository {
+				mock := mocks.NewFileRepositoryMock(mc)
 				mock.DeleteMock.Return(nil)
 				return mock
 			},
@@ -171,10 +171,15 @@ func Test_DeleteThingImageHandler(t *testing.T) {
 
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
+			t.Parallel()
+
+			mc := minimock.NewController(t)
 			fiberApp := fiber.New()
-			serviceProvider := sp.InitMock(tt.thingImageRepoMock(mc), tt.fileRepoMock(mc))
 
-			fiberApp.Delete("/v1/images/thing/:imageId", DeleteThingImageHandler(serviceProvider))
+			fiberApp.Delete("/v1/images/thing/:imageId", DeleteThingImageHandler(
+				tt.fileRepoMock(mc),
+				tt.thingImageRepoMock(mc),
+			))
 
 			fiberRes, _ := fiberApp.Test(httptest.NewRequest(tt.req.method, tt.req.route, nil), API.DefaultTestTimeOut)
 

+ 9 - 6
internal/api/v1/image/get_place_images.go

@@ -3,11 +3,11 @@ package image
 import (
 	"sort"
 
+	"github.com/gofiber/fiber/v2"
+
 	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/mappers"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
-	"github.com/gofiber/fiber/v2"
 )
 
 // @Router 		/api/v1/images/place/{placeId} [get]
@@ -20,7 +20,10 @@ import (
 // @security 	APIKey
 // @Accept      json
 // @Produce     json
-func GetPlaceImagesHandler(sp interfaces.ServiceProvider) fiber.Handler {
+func GetPlaceImagesHandler(
+	thingImageRepository ThingImageRepository,
+	placeImageRepository PlaceImageRepository,
+) fiber.Handler {
 	return func(fctx *fiber.Ctx) error {
 		var res []models.Image
 		ctx := fctx.Context()
@@ -29,13 +32,13 @@ func GetPlaceImagesHandler(sp interfaces.ServiceProvider) fiber.Handler {
 			return fiber.NewError(fiber.StatusBadRequest, err.Error())
 		}
 
-		placesRes, err := sp.GetPlaceImageRepository().GetByPlaceID(ctx, id)
+		placesRes, err := placeImageRepository.GetByPlaceID(ctx, id)
 		if err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 		res = append(res, placesRes...)
 
-		thingsRes, err := sp.GetThingImageRepository().GetByPlaceID(ctx, id)
+		thingsRes, err := thingImageRepository.GetByPlaceID(ctx, id)
 		if err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
@@ -47,6 +50,6 @@ func GetPlaceImagesHandler(sp interfaces.ServiceProvider) fiber.Handler {
 
 		res = helpers.ApplyLocation(fctx, res)
 
-		return fctx.JSON(mappers.ConvertToImagesResponseDTO(res))
+		return fctx.JSON(mappers.ToImagesResponse(res))
 	}
 }

+ 34 - 29
internal/api/v1/image/get_place_images_test.go

@@ -9,27 +9,27 @@ import (
 	"testing"
 	"time"
 
-	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
-	repoMocks "git.dmitriygnatenko.ru/dima/homethings/internal/repositories/mocks"
-	sp "git.dmitriygnatenko.ru/dima/homethings/internal/service_provider"
 	"github.com/brianvoe/gofakeit/v6"
 	"github.com/gofiber/fiber/v2"
 	"github.com/gojuno/minimock/v3"
 	"github.com/stretchr/testify/assert"
+
+	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/image/mocks"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
 )
 
-func Test_GetPlaceImagesHandler(t *testing.T) {
+func TestGetPlaceImagesHandler(t *testing.T) {
+	t.Parallel()
+
 	type req struct {
 		method string
 		route  string
 	}
 
 	var (
-		mc        = minimock.NewController(t)
 		placeID   = gofakeit.Number(1, 1000)
 		thingID   = gofakeit.Number(1, 1000)
 		date1     = gofakeit.Date()
@@ -96,8 +96,8 @@ func Test_GetPlaceImagesHandler(t *testing.T) {
 		req                req
 		resCode            int
 		resBody            interface{}
-		thingImageRepoMock func(mc *minimock.Controller) interfaces.ThingImageRepository
-		placeImageRepoMock func(mc *minimock.Controller) interfaces.PlaceImageRepository
+		thingImageRepoMock func(mc *minimock.Controller) ThingImageRepository
+		placeImageRepoMock func(mc *minimock.Controller) PlaceImageRepository
 	}{
 		{
 			name: "negative case - bad request",
@@ -106,19 +106,19 @@ func Test_GetPlaceImagesHandler(t *testing.T) {
 				route:  "/v1/images/place/" + gofakeit.Word(),
 			},
 			resCode: fiber.StatusBadRequest,
-			placeImageRepoMock: func(mc *minimock.Controller) interfaces.PlaceImageRepository {
-				return repoMocks.NewPlaceImageRepositoryMock(mc)
+			placeImageRepoMock: func(mc *minimock.Controller) PlaceImageRepository {
+				return mocks.NewPlaceImageRepositoryMock(mc)
 			},
-			thingImageRepoMock: func(mc *minimock.Controller) interfaces.ThingImageRepository {
-				return repoMocks.NewThingImageRepositoryMock(mc)
+			thingImageRepoMock: func(mc *minimock.Controller) ThingImageRepository {
+				return mocks.NewThingImageRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - place repository error",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			placeImageRepoMock: func(mc *minimock.Controller) interfaces.PlaceImageRepository {
-				mock := repoMocks.NewPlaceImageRepositoryMock(mc)
+			placeImageRepoMock: func(mc *minimock.Controller) PlaceImageRepository {
+				mock := mocks.NewPlaceImageRepositoryMock(mc)
 
 				mock.GetByPlaceIDMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, placeID, id)
@@ -126,16 +126,16 @@ func Test_GetPlaceImagesHandler(t *testing.T) {
 
 				return mock
 			},
-			thingImageRepoMock: func(mc *minimock.Controller) interfaces.ThingImageRepository {
-				return repoMocks.NewThingImageRepositoryMock(mc)
+			thingImageRepoMock: func(mc *minimock.Controller) ThingImageRepository {
+				return mocks.NewThingImageRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - thing repository error",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			placeImageRepoMock: func(mc *minimock.Controller) interfaces.PlaceImageRepository {
-				mock := repoMocks.NewPlaceImageRepositoryMock(mc)
+			placeImageRepoMock: func(mc *minimock.Controller) PlaceImageRepository {
+				mock := mocks.NewPlaceImageRepositoryMock(mc)
 
 				mock.GetByPlaceIDMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, placeID, id)
@@ -143,8 +143,8 @@ func Test_GetPlaceImagesHandler(t *testing.T) {
 
 				return mock
 			},
-			thingImageRepoMock: func(mc *minimock.Controller) interfaces.ThingImageRepository {
-				mock := repoMocks.NewThingImageRepositoryMock(mc)
+			thingImageRepoMock: func(mc *minimock.Controller) ThingImageRepository {
+				mock := mocks.NewThingImageRepositoryMock(mc)
 
 				mock.GetByPlaceIDMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, placeID, id)
@@ -158,8 +158,8 @@ func Test_GetPlaceImagesHandler(t *testing.T) {
 			req:     correctReq,
 			resCode: fiber.StatusOK,
 			resBody: expectedRes,
-			placeImageRepoMock: func(mc *minimock.Controller) interfaces.PlaceImageRepository {
-				mock := repoMocks.NewPlaceImageRepositoryMock(mc)
+			placeImageRepoMock: func(mc *minimock.Controller) PlaceImageRepository {
+				mock := mocks.NewPlaceImageRepositoryMock(mc)
 
 				mock.GetByPlaceIDMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, placeID, id)
@@ -167,8 +167,8 @@ func Test_GetPlaceImagesHandler(t *testing.T) {
 
 				return mock
 			},
-			thingImageRepoMock: func(mc *minimock.Controller) interfaces.ThingImageRepository {
-				mock := repoMocks.NewThingImageRepositoryMock(mc)
+			thingImageRepoMock: func(mc *minimock.Controller) ThingImageRepository {
+				mock := mocks.NewThingImageRepositoryMock(mc)
 
 				mock.GetByPlaceIDMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, placeID, id)
@@ -181,10 +181,15 @@ func Test_GetPlaceImagesHandler(t *testing.T) {
 
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
+			t.Parallel()
+
+			mc := minimock.NewController(t)
 			fiberApp := fiber.New()
-			serviceProvider := sp.InitMock(tt.thingImageRepoMock(mc), tt.placeImageRepoMock(mc))
 
-			fiberApp.Get("/v1/images/place/:placeId", GetPlaceImagesHandler(serviceProvider))
+			fiberApp.Get("/v1/images/place/:placeId", GetPlaceImagesHandler(
+				tt.thingImageRepoMock(mc),
+				tt.placeImageRepoMock(mc),
+			))
 
 			fiberRes, _ := fiberApp.Test(httptest.NewRequest(tt.req.method, tt.req.route, nil), API.DefaultTestTimeOut)
 

+ 7 - 5
internal/api/v1/image/get_thing_images.go

@@ -1,10 +1,10 @@
 package image
 
 import (
+	"github.com/gofiber/fiber/v2"
+
 	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/mappers"
-	"github.com/gofiber/fiber/v2"
 )
 
 // @Router 		/api/v1/images/thing/{thingId} [get]
@@ -17,7 +17,9 @@ import (
 // @security 	APIKey
 // @Accept      json
 // @Produce     json
-func GetThingImagesHandler(sp interfaces.ServiceProvider) fiber.Handler {
+func GetThingImagesHandler(
+	thingImageRepository ThingImageRepository,
+) fiber.Handler {
 	return func(fctx *fiber.Ctx) error {
 		ctx := fctx.Context()
 		id, err := fctx.ParamsInt("thingId")
@@ -25,13 +27,13 @@ func GetThingImagesHandler(sp interfaces.ServiceProvider) fiber.Handler {
 			return fiber.NewError(fiber.StatusBadRequest, err.Error())
 		}
 
-		res, err := sp.GetThingImageRepository().GetByThingID(ctx, id)
+		res, err := thingImageRepository.GetByThingID(ctx, id)
 		if err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
 		res = helpers.ApplyLocation(fctx, res)
 
-		return fctx.JSON(mappers.ConvertToImagesResponseDTO(res))
+		return fctx.JSON(mappers.ToImagesResponse(res))
 	}
 }

+ 20 - 18
internal/api/v1/image/get_thing_images_test.go

@@ -8,27 +8,27 @@ import (
 	"strconv"
 	"testing"
 
-	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
-	repoMocks "git.dmitriygnatenko.ru/dima/homethings/internal/repositories/mocks"
-	sp "git.dmitriygnatenko.ru/dima/homethings/internal/service_provider"
 	"github.com/brianvoe/gofakeit/v6"
 	"github.com/gofiber/fiber/v2"
 	"github.com/gojuno/minimock/v3"
 	"github.com/stretchr/testify/assert"
+
+	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/image/mocks"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
 )
 
-func Test_GetThingImagesHandler(t *testing.T) {
+func TestGetThingImagesHandler(t *testing.T) {
+	t.Parallel()
+
 	type req struct {
 		method string
 		route  string
 	}
 
 	var (
-		mc        = minimock.NewController(t)
 		thingID   = gofakeit.Number(1, 1000)
 		testError = errors.New(gofakeit.Phrase())
 		layout    = "2006-01-02 15:04:05"
@@ -88,7 +88,7 @@ func Test_GetThingImagesHandler(t *testing.T) {
 		req                req
 		resCode            int
 		resBody            interface{}
-		thingImageRepoMock func(mc *minimock.Controller) interfaces.ThingImageRepository
+		thingImageRepoMock func(mc *minimock.Controller) ThingImageRepository
 	}{
 		{
 			name: "negative case - bad request",
@@ -97,16 +97,16 @@ func Test_GetThingImagesHandler(t *testing.T) {
 				route:  "/v1/images/thing/" + gofakeit.Word(),
 			},
 			resCode: fiber.StatusBadRequest,
-			thingImageRepoMock: func(mc *minimock.Controller) interfaces.ThingImageRepository {
-				return repoMocks.NewThingImageRepositoryMock(mc)
+			thingImageRepoMock: func(mc *minimock.Controller) ThingImageRepository {
+				return mocks.NewThingImageRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - repository error",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			thingImageRepoMock: func(mc *minimock.Controller) interfaces.ThingImageRepository {
-				mock := repoMocks.NewThingImageRepositoryMock(mc)
+			thingImageRepoMock: func(mc *minimock.Controller) ThingImageRepository {
+				mock := mocks.NewThingImageRepositoryMock(mc)
 
 				mock.GetByThingIDMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -120,8 +120,8 @@ func Test_GetThingImagesHandler(t *testing.T) {
 			req:     correctReq,
 			resCode: fiber.StatusOK,
 			resBody: expectedRes,
-			thingImageRepoMock: func(mc *minimock.Controller) interfaces.ThingImageRepository {
-				mock := repoMocks.NewThingImageRepositoryMock(mc)
+			thingImageRepoMock: func(mc *minimock.Controller) ThingImageRepository {
+				mock := mocks.NewThingImageRepositoryMock(mc)
 
 				mock.GetByThingIDMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -134,10 +134,12 @@ func Test_GetThingImagesHandler(t *testing.T) {
 
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
+			t.Parallel()
+
+			mc := minimock.NewController(t)
 			fiberApp := fiber.New()
-			serviceProvider := sp.InitMock(tt.thingImageRepoMock(mc))
 
-			fiberApp.Get("/v1/images/thing/:thingId", GetThingImagesHandler(serviceProvider))
+			fiberApp.Get("/v1/images/thing/:thingId", GetThingImagesHandler(tt.thingImageRepoMock(mc)))
 
 			fiberRes, _ := fiberApp.Test(httptest.NewRequest(tt.req.method, tt.req.route, nil), API.DefaultTestTimeOut)
 

+ 264 - 51
internal/repositories/mocks/file_repository_minimock.go → internal/api/v1/image/mocks/file_repository_minimock.go

@@ -1,8 +1,8 @@
-package mocks
+// Code generated by http://github.com/gojuno/minimock (v3.3.13). DO NOT EDIT.
 
-// Code generated by http://github.com/gojuno/minimock (dev). DO NOT EDIT.
+package mocks
 
-//go:generate minimock -i git.dmitriygnatenko.ru/dima/homethings/internal/interfaces.FileRepository -o ./mocks/file_repository_minimock.go -n FileRepositoryMock
+//go:generate minimock -i git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/image.FileRepository -o file_repository_minimock.go -n FileRepositoryMock -p mocks
 
 import (
 	"mime/multipart"
@@ -14,9 +14,10 @@ import (
 	"github.com/gojuno/minimock/v3"
 )
 
-// FileRepositoryMock implements interfaces.FileRepository
+// FileRepositoryMock implements image.FileRepository
 type FileRepositoryMock struct {
-	t minimock.Tester
+	t          minimock.Tester
+	finishOnce sync.Once
 
 	funcDelete          func(path string) (err error)
 	inspectFuncDelete   func(path string)
@@ -31,9 +32,10 @@ type FileRepositoryMock struct {
 	SaveMock          mFileRepositoryMockSave
 }
 
-// NewFileRepositoryMock returns a mock for interfaces.FileRepository
+// NewFileRepositoryMock returns a mock for image.FileRepository
 func NewFileRepositoryMock(t minimock.Tester) *FileRepositoryMock {
 	m := &FileRepositoryMock{t: t}
+
 	if controller, ok := t.(minimock.MockController); ok {
 		controller.RegisterMocker(m)
 	}
@@ -44,24 +46,30 @@ func NewFileRepositoryMock(t minimock.Tester) *FileRepositoryMock {
 	m.SaveMock = mFileRepositoryMockSave{mock: m}
 	m.SaveMock.callArgs = []*FileRepositoryMockSaveParams{}
 
+	t.Cleanup(m.MinimockFinish)
+
 	return m
 }
 
 type mFileRepositoryMockDelete struct {
+	optional           bool
 	mock               *FileRepositoryMock
 	defaultExpectation *FileRepositoryMockDeleteExpectation
 	expectations       []*FileRepositoryMockDeleteExpectation
 
 	callArgs []*FileRepositoryMockDeleteParams
 	mutex    sync.RWMutex
+
+	expectedInvocations uint64
 }
 
 // FileRepositoryMockDeleteExpectation specifies expectation struct of the FileRepository.Delete
 type FileRepositoryMockDeleteExpectation struct {
-	mock    *FileRepositoryMock
-	params  *FileRepositoryMockDeleteParams
-	results *FileRepositoryMockDeleteResults
-	Counter uint64
+	mock      *FileRepositoryMock
+	params    *FileRepositoryMockDeleteParams
+	paramPtrs *FileRepositoryMockDeleteParamPtrs
+	results   *FileRepositoryMockDeleteResults
+	Counter   uint64
 }
 
 // FileRepositoryMockDeleteParams contains parameters of the FileRepository.Delete
@@ -69,11 +77,26 @@ type FileRepositoryMockDeleteParams struct {
 	path string
 }
 
+// FileRepositoryMockDeleteParamPtrs contains pointers to parameters of the FileRepository.Delete
+type FileRepositoryMockDeleteParamPtrs struct {
+	path *string
+}
+
 // FileRepositoryMockDeleteResults contains results of the FileRepository.Delete
 type FileRepositoryMockDeleteResults struct {
 	err error
 }
 
+// Marks this method to be optional. The default behavior of any method with Return() is '1 or more', meaning
+// the test will fail minimock's automatic final call check if the mocked method was not called at least once.
+// Optional() makes method check to work in '0 or more' mode.
+// It is NOT RECOMMENDED to use this option unless you really need it, as default behaviour helps to
+// catch the problems when the expected method call is totally skipped during test run.
+func (mmDelete *mFileRepositoryMockDelete) Optional() *mFileRepositoryMockDelete {
+	mmDelete.optional = true
+	return mmDelete
+}
+
 // Expect sets up expected params for FileRepository.Delete
 func (mmDelete *mFileRepositoryMockDelete) Expect(path string) *mFileRepositoryMockDelete {
 	if mmDelete.mock.funcDelete != nil {
@@ -84,6 +107,10 @@ func (mmDelete *mFileRepositoryMockDelete) Expect(path string) *mFileRepositoryM
 		mmDelete.defaultExpectation = &FileRepositoryMockDeleteExpectation{}
 	}
 
+	if mmDelete.defaultExpectation.paramPtrs != nil {
+		mmDelete.mock.t.Fatalf("FileRepositoryMock.Delete mock is already set by ExpectParams functions")
+	}
+
 	mmDelete.defaultExpectation.params = &FileRepositoryMockDeleteParams{path}
 	for _, e := range mmDelete.expectations {
 		if minimock.Equal(e.params, mmDelete.defaultExpectation.params) {
@@ -94,6 +121,28 @@ func (mmDelete *mFileRepositoryMockDelete) Expect(path string) *mFileRepositoryM
 	return mmDelete
 }
 
+// ExpectPathParam1 sets up expected param path for FileRepository.Delete
+func (mmDelete *mFileRepositoryMockDelete) ExpectPathParam1(path string) *mFileRepositoryMockDelete {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("FileRepositoryMock.Delete mock is already set by Set")
+	}
+
+	if mmDelete.defaultExpectation == nil {
+		mmDelete.defaultExpectation = &FileRepositoryMockDeleteExpectation{}
+	}
+
+	if mmDelete.defaultExpectation.params != nil {
+		mmDelete.mock.t.Fatalf("FileRepositoryMock.Delete mock is already set by Expect")
+	}
+
+	if mmDelete.defaultExpectation.paramPtrs == nil {
+		mmDelete.defaultExpectation.paramPtrs = &FileRepositoryMockDeleteParamPtrs{}
+	}
+	mmDelete.defaultExpectation.paramPtrs.path = &path
+
+	return mmDelete
+}
+
 // Inspect accepts an inspector function that has same arguments as the FileRepository.Delete
 func (mmDelete *mFileRepositoryMockDelete) Inspect(f func(path string)) *mFileRepositoryMockDelete {
 	if mmDelete.mock.inspectFuncDelete != nil {
@@ -153,7 +202,27 @@ func (e *FileRepositoryMockDeleteExpectation) Then(err error) *FileRepositoryMoc
 	return e.mock
 }
 
-// Delete implements interfaces.FileRepository
+// Times sets number of times FileRepository.Delete should be invoked
+func (mmDelete *mFileRepositoryMockDelete) Times(n uint64) *mFileRepositoryMockDelete {
+	if n == 0 {
+		mmDelete.mock.t.Fatalf("Times of FileRepositoryMock.Delete mock can not be zero")
+	}
+	mm_atomic.StoreUint64(&mmDelete.expectedInvocations, n)
+	return mmDelete
+}
+
+func (mmDelete *mFileRepositoryMockDelete) invocationsDone() bool {
+	if len(mmDelete.expectations) == 0 && mmDelete.defaultExpectation == nil && mmDelete.mock.funcDelete == nil {
+		return true
+	}
+
+	totalInvocations := mm_atomic.LoadUint64(&mmDelete.mock.afterDeleteCounter)
+	expectedInvocations := mm_atomic.LoadUint64(&mmDelete.expectedInvocations)
+
+	return totalInvocations > 0 && (expectedInvocations == 0 || expectedInvocations == totalInvocations)
+}
+
+// Delete implements image.FileRepository
 func (mmDelete *FileRepositoryMock) Delete(path string) (err error) {
 	mm_atomic.AddUint64(&mmDelete.beforeDeleteCounter, 1)
 	defer mm_atomic.AddUint64(&mmDelete.afterDeleteCounter, 1)
@@ -162,15 +231,15 @@ func (mmDelete *FileRepositoryMock) Delete(path string) (err error) {
 		mmDelete.inspectFuncDelete(path)
 	}
 
-	mm_params := &FileRepositoryMockDeleteParams{path}
+	mm_params := FileRepositoryMockDeleteParams{path}
 
 	// Record call args
 	mmDelete.DeleteMock.mutex.Lock()
-	mmDelete.DeleteMock.callArgs = append(mmDelete.DeleteMock.callArgs, mm_params)
+	mmDelete.DeleteMock.callArgs = append(mmDelete.DeleteMock.callArgs, &mm_params)
 	mmDelete.DeleteMock.mutex.Unlock()
 
 	for _, e := range mmDelete.DeleteMock.expectations {
-		if minimock.Equal(e.params, mm_params) {
+		if minimock.Equal(*e.params, mm_params) {
 			mm_atomic.AddUint64(&e.Counter, 1)
 			return e.results.err
 		}
@@ -179,8 +248,17 @@ func (mmDelete *FileRepositoryMock) Delete(path string) (err error) {
 	if mmDelete.DeleteMock.defaultExpectation != nil {
 		mm_atomic.AddUint64(&mmDelete.DeleteMock.defaultExpectation.Counter, 1)
 		mm_want := mmDelete.DeleteMock.defaultExpectation.params
+		mm_want_ptrs := mmDelete.DeleteMock.defaultExpectation.paramPtrs
+
 		mm_got := FileRepositoryMockDeleteParams{path}
-		if mm_want != nil && !minimock.Equal(*mm_want, mm_got) {
+
+		if mm_want_ptrs != nil {
+
+			if mm_want_ptrs.path != nil && !minimock.Equal(*mm_want_ptrs.path, mm_got.path) {
+				mmDelete.t.Errorf("FileRepositoryMock.Delete got unexpected parameter path, want: %#v, got: %#v%s\n", *mm_want_ptrs.path, mm_got.path, minimock.Diff(*mm_want_ptrs.path, mm_got.path))
+			}
+
+		} else if mm_want != nil && !minimock.Equal(*mm_want, mm_got) {
 			mmDelete.t.Errorf("FileRepositoryMock.Delete got unexpected parameters, want: %#v, got: %#v%s\n", *mm_want, mm_got, minimock.Diff(*mm_want, mm_got))
 		}
 
@@ -223,21 +301,18 @@ func (mmDelete *mFileRepositoryMockDelete) Calls() []*FileRepositoryMockDeletePa
 // MinimockDeleteDone returns true if the count of the Delete invocations corresponds
 // the number of defined expectations
 func (m *FileRepositoryMock) MinimockDeleteDone() bool {
+	if m.DeleteMock.optional {
+		// Optional methods provide '0 or more' call count restriction.
+		return true
+	}
+
 	for _, e := range m.DeleteMock.expectations {
 		if mm_atomic.LoadUint64(&e.Counter) < 1 {
 			return false
 		}
 	}
 
-	// if default expectation was set then invocations count should be greater than zero
-	if m.DeleteMock.defaultExpectation != nil && mm_atomic.LoadUint64(&m.afterDeleteCounter) < 1 {
-		return false
-	}
-	// if func was set then invocations count should be greater than zero
-	if m.funcDelete != nil && mm_atomic.LoadUint64(&m.afterDeleteCounter) < 1 {
-		return false
-	}
-	return true
+	return m.DeleteMock.invocationsDone()
 }
 
 // MinimockDeleteInspect logs each unmet expectation
@@ -248,8 +323,9 @@ func (m *FileRepositoryMock) MinimockDeleteInspect() {
 		}
 	}
 
+	afterDeleteCounter := mm_atomic.LoadUint64(&m.afterDeleteCounter)
 	// if default expectation was set then invocations count should be greater than zero
-	if m.DeleteMock.defaultExpectation != nil && mm_atomic.LoadUint64(&m.afterDeleteCounter) < 1 {
+	if m.DeleteMock.defaultExpectation != nil && afterDeleteCounter < 1 {
 		if m.DeleteMock.defaultExpectation.params == nil {
 			m.t.Error("Expected call to FileRepositoryMock.Delete")
 		} else {
@@ -257,26 +333,35 @@ func (m *FileRepositoryMock) MinimockDeleteInspect() {
 		}
 	}
 	// if func was set then invocations count should be greater than zero
-	if m.funcDelete != nil && mm_atomic.LoadUint64(&m.afterDeleteCounter) < 1 {
+	if m.funcDelete != nil && afterDeleteCounter < 1 {
 		m.t.Error("Expected call to FileRepositoryMock.Delete")
 	}
+
+	if !m.DeleteMock.invocationsDone() && afterDeleteCounter > 0 {
+		m.t.Errorf("Expected %d calls to FileRepositoryMock.Delete but found %d calls",
+			mm_atomic.LoadUint64(&m.DeleteMock.expectedInvocations), afterDeleteCounter)
+	}
 }
 
 type mFileRepositoryMockSave struct {
+	optional           bool
 	mock               *FileRepositoryMock
 	defaultExpectation *FileRepositoryMockSaveExpectation
 	expectations       []*FileRepositoryMockSaveExpectation
 
 	callArgs []*FileRepositoryMockSaveParams
 	mutex    sync.RWMutex
+
+	expectedInvocations uint64
 }
 
 // FileRepositoryMockSaveExpectation specifies expectation struct of the FileRepository.Save
 type FileRepositoryMockSaveExpectation struct {
-	mock    *FileRepositoryMock
-	params  *FileRepositoryMockSaveParams
-	results *FileRepositoryMockSaveResults
-	Counter uint64
+	mock      *FileRepositoryMock
+	params    *FileRepositoryMockSaveParams
+	paramPtrs *FileRepositoryMockSaveParamPtrs
+	results   *FileRepositoryMockSaveResults
+	Counter   uint64
 }
 
 // FileRepositoryMockSaveParams contains parameters of the FileRepository.Save
@@ -286,11 +371,28 @@ type FileRepositoryMockSaveParams struct {
 	path   string
 }
 
+// FileRepositoryMockSaveParamPtrs contains pointers to parameters of the FileRepository.Save
+type FileRepositoryMockSaveParamPtrs struct {
+	fctx   **fiber.Ctx
+	header **multipart.FileHeader
+	path   *string
+}
+
 // FileRepositoryMockSaveResults contains results of the FileRepository.Save
 type FileRepositoryMockSaveResults struct {
 	err error
 }
 
+// Marks this method to be optional. The default behavior of any method with Return() is '1 or more', meaning
+// the test will fail minimock's automatic final call check if the mocked method was not called at least once.
+// Optional() makes method check to work in '0 or more' mode.
+// It is NOT RECOMMENDED to use this option unless you really need it, as default behaviour helps to
+// catch the problems when the expected method call is totally skipped during test run.
+func (mmSave *mFileRepositoryMockSave) Optional() *mFileRepositoryMockSave {
+	mmSave.optional = true
+	return mmSave
+}
+
 // Expect sets up expected params for FileRepository.Save
 func (mmSave *mFileRepositoryMockSave) Expect(fctx *fiber.Ctx, header *multipart.FileHeader, path string) *mFileRepositoryMockSave {
 	if mmSave.mock.funcSave != nil {
@@ -301,6 +403,10 @@ func (mmSave *mFileRepositoryMockSave) Expect(fctx *fiber.Ctx, header *multipart
 		mmSave.defaultExpectation = &FileRepositoryMockSaveExpectation{}
 	}
 
+	if mmSave.defaultExpectation.paramPtrs != nil {
+		mmSave.mock.t.Fatalf("FileRepositoryMock.Save mock is already set by ExpectParams functions")
+	}
+
 	mmSave.defaultExpectation.params = &FileRepositoryMockSaveParams{fctx, header, path}
 	for _, e := range mmSave.expectations {
 		if minimock.Equal(e.params, mmSave.defaultExpectation.params) {
@@ -311,6 +417,72 @@ func (mmSave *mFileRepositoryMockSave) Expect(fctx *fiber.Ctx, header *multipart
 	return mmSave
 }
 
+// ExpectFctxParam1 sets up expected param fctx for FileRepository.Save
+func (mmSave *mFileRepositoryMockSave) ExpectFctxParam1(fctx *fiber.Ctx) *mFileRepositoryMockSave {
+	if mmSave.mock.funcSave != nil {
+		mmSave.mock.t.Fatalf("FileRepositoryMock.Save mock is already set by Set")
+	}
+
+	if mmSave.defaultExpectation == nil {
+		mmSave.defaultExpectation = &FileRepositoryMockSaveExpectation{}
+	}
+
+	if mmSave.defaultExpectation.params != nil {
+		mmSave.mock.t.Fatalf("FileRepositoryMock.Save mock is already set by Expect")
+	}
+
+	if mmSave.defaultExpectation.paramPtrs == nil {
+		mmSave.defaultExpectation.paramPtrs = &FileRepositoryMockSaveParamPtrs{}
+	}
+	mmSave.defaultExpectation.paramPtrs.fctx = &fctx
+
+	return mmSave
+}
+
+// ExpectHeaderParam2 sets up expected param header for FileRepository.Save
+func (mmSave *mFileRepositoryMockSave) ExpectHeaderParam2(header *multipart.FileHeader) *mFileRepositoryMockSave {
+	if mmSave.mock.funcSave != nil {
+		mmSave.mock.t.Fatalf("FileRepositoryMock.Save mock is already set by Set")
+	}
+
+	if mmSave.defaultExpectation == nil {
+		mmSave.defaultExpectation = &FileRepositoryMockSaveExpectation{}
+	}
+
+	if mmSave.defaultExpectation.params != nil {
+		mmSave.mock.t.Fatalf("FileRepositoryMock.Save mock is already set by Expect")
+	}
+
+	if mmSave.defaultExpectation.paramPtrs == nil {
+		mmSave.defaultExpectation.paramPtrs = &FileRepositoryMockSaveParamPtrs{}
+	}
+	mmSave.defaultExpectation.paramPtrs.header = &header
+
+	return mmSave
+}
+
+// ExpectPathParam3 sets up expected param path for FileRepository.Save
+func (mmSave *mFileRepositoryMockSave) ExpectPathParam3(path string) *mFileRepositoryMockSave {
+	if mmSave.mock.funcSave != nil {
+		mmSave.mock.t.Fatalf("FileRepositoryMock.Save mock is already set by Set")
+	}
+
+	if mmSave.defaultExpectation == nil {
+		mmSave.defaultExpectation = &FileRepositoryMockSaveExpectation{}
+	}
+
+	if mmSave.defaultExpectation.params != nil {
+		mmSave.mock.t.Fatalf("FileRepositoryMock.Save mock is already set by Expect")
+	}
+
+	if mmSave.defaultExpectation.paramPtrs == nil {
+		mmSave.defaultExpectation.paramPtrs = &FileRepositoryMockSaveParamPtrs{}
+	}
+	mmSave.defaultExpectation.paramPtrs.path = &path
+
+	return mmSave
+}
+
 // Inspect accepts an inspector function that has same arguments as the FileRepository.Save
 func (mmSave *mFileRepositoryMockSave) Inspect(f func(fctx *fiber.Ctx, header *multipart.FileHeader, path string)) *mFileRepositoryMockSave {
 	if mmSave.mock.inspectFuncSave != nil {
@@ -370,7 +542,27 @@ func (e *FileRepositoryMockSaveExpectation) Then(err error) *FileRepositoryMock
 	return e.mock
 }
 
-// Save implements interfaces.FileRepository
+// Times sets number of times FileRepository.Save should be invoked
+func (mmSave *mFileRepositoryMockSave) Times(n uint64) *mFileRepositoryMockSave {
+	if n == 0 {
+		mmSave.mock.t.Fatalf("Times of FileRepositoryMock.Save mock can not be zero")
+	}
+	mm_atomic.StoreUint64(&mmSave.expectedInvocations, n)
+	return mmSave
+}
+
+func (mmSave *mFileRepositoryMockSave) invocationsDone() bool {
+	if len(mmSave.expectations) == 0 && mmSave.defaultExpectation == nil && mmSave.mock.funcSave == nil {
+		return true
+	}
+
+	totalInvocations := mm_atomic.LoadUint64(&mmSave.mock.afterSaveCounter)
+	expectedInvocations := mm_atomic.LoadUint64(&mmSave.expectedInvocations)
+
+	return totalInvocations > 0 && (expectedInvocations == 0 || expectedInvocations == totalInvocations)
+}
+
+// Save implements image.FileRepository
 func (mmSave *FileRepositoryMock) Save(fctx *fiber.Ctx, header *multipart.FileHeader, path string) (err error) {
 	mm_atomic.AddUint64(&mmSave.beforeSaveCounter, 1)
 	defer mm_atomic.AddUint64(&mmSave.afterSaveCounter, 1)
@@ -379,15 +571,15 @@ func (mmSave *FileRepositoryMock) Save(fctx *fiber.Ctx, header *multipart.FileHe
 		mmSave.inspectFuncSave(fctx, header, path)
 	}
 
-	mm_params := &FileRepositoryMockSaveParams{fctx, header, path}
+	mm_params := FileRepositoryMockSaveParams{fctx, header, path}
 
 	// Record call args
 	mmSave.SaveMock.mutex.Lock()
-	mmSave.SaveMock.callArgs = append(mmSave.SaveMock.callArgs, mm_params)
+	mmSave.SaveMock.callArgs = append(mmSave.SaveMock.callArgs, &mm_params)
 	mmSave.SaveMock.mutex.Unlock()
 
 	for _, e := range mmSave.SaveMock.expectations {
-		if minimock.Equal(e.params, mm_params) {
+		if minimock.Equal(*e.params, mm_params) {
 			mm_atomic.AddUint64(&e.Counter, 1)
 			return e.results.err
 		}
@@ -396,8 +588,25 @@ func (mmSave *FileRepositoryMock) Save(fctx *fiber.Ctx, header *multipart.FileHe
 	if mmSave.SaveMock.defaultExpectation != nil {
 		mm_atomic.AddUint64(&mmSave.SaveMock.defaultExpectation.Counter, 1)
 		mm_want := mmSave.SaveMock.defaultExpectation.params
+		mm_want_ptrs := mmSave.SaveMock.defaultExpectation.paramPtrs
+
 		mm_got := FileRepositoryMockSaveParams{fctx, header, path}
-		if mm_want != nil && !minimock.Equal(*mm_want, mm_got) {
+
+		if mm_want_ptrs != nil {
+
+			if mm_want_ptrs.fctx != nil && !minimock.Equal(*mm_want_ptrs.fctx, mm_got.fctx) {
+				mmSave.t.Errorf("FileRepositoryMock.Save got unexpected parameter fctx, want: %#v, got: %#v%s\n", *mm_want_ptrs.fctx, mm_got.fctx, minimock.Diff(*mm_want_ptrs.fctx, mm_got.fctx))
+			}
+
+			if mm_want_ptrs.header != nil && !minimock.Equal(*mm_want_ptrs.header, mm_got.header) {
+				mmSave.t.Errorf("FileRepositoryMock.Save got unexpected parameter header, want: %#v, got: %#v%s\n", *mm_want_ptrs.header, mm_got.header, minimock.Diff(*mm_want_ptrs.header, mm_got.header))
+			}
+
+			if mm_want_ptrs.path != nil && !minimock.Equal(*mm_want_ptrs.path, mm_got.path) {
+				mmSave.t.Errorf("FileRepositoryMock.Save got unexpected parameter path, want: %#v, got: %#v%s\n", *mm_want_ptrs.path, mm_got.path, minimock.Diff(*mm_want_ptrs.path, mm_got.path))
+			}
+
+		} else if mm_want != nil && !minimock.Equal(*mm_want, mm_got) {
 			mmSave.t.Errorf("FileRepositoryMock.Save got unexpected parameters, want: %#v, got: %#v%s\n", *mm_want, mm_got, minimock.Diff(*mm_want, mm_got))
 		}
 
@@ -440,21 +649,18 @@ func (mmSave *mFileRepositoryMockSave) Calls() []*FileRepositoryMockSaveParams {
 // MinimockSaveDone returns true if the count of the Save invocations corresponds
 // the number of defined expectations
 func (m *FileRepositoryMock) MinimockSaveDone() bool {
+	if m.SaveMock.optional {
+		// Optional methods provide '0 or more' call count restriction.
+		return true
+	}
+
 	for _, e := range m.SaveMock.expectations {
 		if mm_atomic.LoadUint64(&e.Counter) < 1 {
 			return false
 		}
 	}
 
-	// if default expectation was set then invocations count should be greater than zero
-	if m.SaveMock.defaultExpectation != nil && mm_atomic.LoadUint64(&m.afterSaveCounter) < 1 {
-		return false
-	}
-	// if func was set then invocations count should be greater than zero
-	if m.funcSave != nil && mm_atomic.LoadUint64(&m.afterSaveCounter) < 1 {
-		return false
-	}
-	return true
+	return m.SaveMock.invocationsDone()
 }
 
 // MinimockSaveInspect logs each unmet expectation
@@ -465,8 +671,9 @@ func (m *FileRepositoryMock) MinimockSaveInspect() {
 		}
 	}
 
+	afterSaveCounter := mm_atomic.LoadUint64(&m.afterSaveCounter)
 	// if default expectation was set then invocations count should be greater than zero
-	if m.SaveMock.defaultExpectation != nil && mm_atomic.LoadUint64(&m.afterSaveCounter) < 1 {
+	if m.SaveMock.defaultExpectation != nil && afterSaveCounter < 1 {
 		if m.SaveMock.defaultExpectation.params == nil {
 			m.t.Error("Expected call to FileRepositoryMock.Save")
 		} else {
@@ -474,19 +681,25 @@ func (m *FileRepositoryMock) MinimockSaveInspect() {
 		}
 	}
 	// if func was set then invocations count should be greater than zero
-	if m.funcSave != nil && mm_atomic.LoadUint64(&m.afterSaveCounter) < 1 {
+	if m.funcSave != nil && afterSaveCounter < 1 {
 		m.t.Error("Expected call to FileRepositoryMock.Save")
 	}
+
+	if !m.SaveMock.invocationsDone() && afterSaveCounter > 0 {
+		m.t.Errorf("Expected %d calls to FileRepositoryMock.Save but found %d calls",
+			mm_atomic.LoadUint64(&m.SaveMock.expectedInvocations), afterSaveCounter)
+	}
 }
 
 // MinimockFinish checks that all mocked methods have been called the expected number of times
 func (m *FileRepositoryMock) MinimockFinish() {
-	if !m.minimockDone() {
-		m.MinimockDeleteInspect()
+	m.finishOnce.Do(func() {
+		if !m.minimockDone() {
+			m.MinimockDeleteInspect()
 
-		m.MinimockSaveInspect()
-		m.t.FailNow()
-	}
+			m.MinimockSaveInspect()
+		}
+	})
 }
 
 // MinimockWait waits for all mocked methods to be called the expected number of times

File diff ditekan karena terlalu besar
+ 525 - 84
internal/api/v1/image/mocks/place_image_repository_minimock.go


File diff ditekan karena terlalu besar
+ 525 - 84
internal/api/v1/image/mocks/thing_image_repository_minimock.go


+ 28 - 8
internal/api/v1/notification/add_thing_notification.go

@@ -1,14 +1,32 @@
 package notification
 
+//go:generate mkdir -p mocks
+//go:generate rm -rf ./mocks/*_minimock.go
+//go:generate minimock -i ThingNotificationRepository -o ./mocks/ -s "_minimock.go"
+
 import (
+	"context"
+	"database/sql"
+
+	"github.com/go-playground/validator/v10"
+	"github.com/gofiber/fiber/v2"
+
 	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/factory"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/mappers"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/repositories"
-	"github.com/go-playground/validator/v10"
-	"github.com/gofiber/fiber/v2"
+)
+
+type (
+	ThingNotificationRepository interface {
+		Add(ctx context.Context, req models.AddThingNotificationRequest, tx *sql.Tx) error
+		Update(ctx context.Context, req models.UpdateThingNotificationRequest, tx *sql.Tx) error
+		Delete(ctx context.Context, thingID int, tx *sql.Tx) error
+		Get(ctx context.Context, thingID int) (*models.ThingNotification, error)
+		GetExpired(ctx context.Context) ([]models.ExtThingNotification, error)
+	}
 )
 
 // @Router 		/api/v1/things/notifications [post]
@@ -21,7 +39,9 @@ import (
 // @security 	APIKey
 // @Accept      json
 // @Produce     json
-func AddThingNotificationHandler(sp interfaces.ServiceProvider) fiber.Handler {
+func AddThingNotificationHandler(
+	thingNotificationRepository ThingNotificationRepository,
+) fiber.Handler {
 	return func(fctx *fiber.Ctx) error {
 		ctx := fctx.Context()
 
@@ -35,12 +55,12 @@ func AddThingNotificationHandler(sp interfaces.ServiceProvider) fiber.Handler {
 			return fctx.Status(fiber.StatusBadRequest).JSON(factory.CreateValidateErrorResponse(err))
 		}
 
-		dbReq, err := mappers.ConvertToAddThingNotificationRequestModel(req)
+		dbReq, err := mappers.ToAddThingNotificationRequest(req)
 		if err != nil {
 			return fiber.NewError(fiber.StatusBadRequest, err.Error())
 		}
 
-		if err = sp.GetThingNotificationRepository().Add(ctx, *dbReq, nil); err != nil {
+		if err = thingNotificationRepository.Add(ctx, *dbReq, nil); err != nil {
 			if repositories.IsFKViolationError(err) || repositories.IsDuplicateKeyError(err) {
 				return fiber.NewError(fiber.StatusBadRequest, "")
 			}
@@ -48,13 +68,13 @@ func AddThingNotificationHandler(sp interfaces.ServiceProvider) fiber.Handler {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
-		res, err := sp.GetThingNotificationRepository().Get(ctx, req.ThingID)
+		res, err := thingNotificationRepository.Get(ctx, req.ThingID)
 		if err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
 		res = helpers.ApplyLocation(fctx, res)
 
-		return fctx.JSON(mappers.ConvertToThingNotificationResponseDTO(*res))
+		return fctx.JSON(mappers.ToThingNotificationResponse(*res))
 	}
 }

+ 29 - 28
internal/api/v1/notification/add_thing_notification_test.go

@@ -8,22 +8,23 @@ import (
 	"testing"
 	"time"
 
-	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/repositories"
-	repoMocks "git.dmitriygnatenko.ru/dima/homethings/internal/repositories/mocks"
-	sp "git.dmitriygnatenko.ru/dima/homethings/internal/service_provider"
 	"github.com/brianvoe/gofakeit/v6"
 	"github.com/gofiber/fiber/v2"
 	"github.com/gojuno/minimock/v3"
 	"github.com/lib/pq"
 	"github.com/stretchr/testify/assert"
+
+	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/notification/mocks"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/repositories"
 )
 
-func Test_AddThingNotificationHandler(t *testing.T) {
+func TestAddThingNotificationHandler(t *testing.T) {
+	t.Parallel()
+
 	type req struct {
 		method      string
 		route       string
@@ -32,7 +33,6 @@ func Test_AddThingNotificationHandler(t *testing.T) {
 	}
 
 	var (
-		mc               = minimock.NewController(t)
 		thingID          = gofakeit.Number(1, 1000)
 		notificationDate = gofakeit.Date().Truncate(time.Second)
 		testError        = errors.New(gofakeit.Phrase())
@@ -68,15 +68,15 @@ func Test_AddThingNotificationHandler(t *testing.T) {
 		req      req
 		resCode  int
 		resBody  interface{}
-		repoMock func(mc *minimock.Controller) interfaces.ThingNotificationRepository
+		repoMock func(mc *minimock.Controller) ThingNotificationRepository
 	}{
 		{
 			name:    "positive case",
 			req:     correctReq,
 			resCode: fiber.StatusOK,
 			resBody: expectedRes,
-			repoMock: func(mc *minimock.Controller) interfaces.ThingNotificationRepository {
-				mock := repoMocks.NewThingNotificationRepositoryMock(mc)
+			repoMock: func(mc *minimock.Controller) ThingNotificationRepository {
+				mock := mocks.NewThingNotificationRepositoryMock(mc)
 
 				mock.AddMock.Inspect(func(ctx context.Context, req models.AddThingNotificationRequest, tx *sql.Tx) {
 					assert.Equal(mc, thingID, req.ThingID)
@@ -97,8 +97,8 @@ func Test_AddThingNotificationHandler(t *testing.T) {
 				route:  "/v1/things/notifications",
 			},
 			resCode: fiber.StatusBadRequest,
-			repoMock: func(mc *minimock.Controller) interfaces.ThingNotificationRepository {
-				return repoMocks.NewThingNotificationRepositoryMock(mc)
+			repoMock: func(mc *minimock.Controller) ThingNotificationRepository {
+				return mocks.NewThingNotificationRepositoryMock(mc)
 			},
 		},
 		{
@@ -112,8 +112,8 @@ func Test_AddThingNotificationHandler(t *testing.T) {
 				contentType: fiber.MIMEApplicationJSON,
 			},
 			resCode: fiber.StatusBadRequest,
-			repoMock: func(mc *minimock.Controller) interfaces.ThingNotificationRepository {
-				return repoMocks.NewThingNotificationRepositoryMock(mc)
+			repoMock: func(mc *minimock.Controller) ThingNotificationRepository {
+				return mocks.NewThingNotificationRepositoryMock(mc)
 			},
 		},
 		{
@@ -128,16 +128,16 @@ func Test_AddThingNotificationHandler(t *testing.T) {
 				contentType: fiber.MIMEApplicationJSON,
 			},
 			resCode: fiber.StatusBadRequest,
-			repoMock: func(mc *minimock.Controller) interfaces.ThingNotificationRepository {
-				return repoMocks.NewThingNotificationRepositoryMock(mc)
+			repoMock: func(mc *minimock.Controller) ThingNotificationRepository {
+				return mocks.NewThingNotificationRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - repository error (add)",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			repoMock: func(mc *minimock.Controller) interfaces.ThingNotificationRepository {
-				mock := repoMocks.NewThingNotificationRepositoryMock(mc)
+			repoMock: func(mc *minimock.Controller) ThingNotificationRepository {
+				mock := mocks.NewThingNotificationRepositoryMock(mc)
 
 				mock.AddMock.Inspect(func(ctx context.Context, req models.AddThingNotificationRequest, tx *sql.Tx) {
 					assert.Equal(mc, thingID, req.ThingID)
@@ -151,8 +151,8 @@ func Test_AddThingNotificationHandler(t *testing.T) {
 			name:    "negative case - repository error (duplicate)",
 			req:     correctReq,
 			resCode: fiber.StatusBadRequest,
-			repoMock: func(mc *minimock.Controller) interfaces.ThingNotificationRepository {
-				mock := repoMocks.NewThingNotificationRepositoryMock(mc)
+			repoMock: func(mc *minimock.Controller) ThingNotificationRepository {
+				mock := mocks.NewThingNotificationRepositoryMock(mc)
 
 				mock.AddMock.Inspect(func(ctx context.Context, req models.AddThingNotificationRequest, tx *sql.Tx) {
 					assert.Equal(mc, thingID, req.ThingID)
@@ -166,8 +166,8 @@ func Test_AddThingNotificationHandler(t *testing.T) {
 			name:    "negative case - repository error (get)",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			repoMock: func(mc *minimock.Controller) interfaces.ThingNotificationRepository {
-				mock := repoMocks.NewThingNotificationRepositoryMock(mc)
+			repoMock: func(mc *minimock.Controller) ThingNotificationRepository {
+				mock := mocks.NewThingNotificationRepositoryMock(mc)
 
 				mock.AddMock.Inspect(func(ctx context.Context, req models.AddThingNotificationRequest, tx *sql.Tx) {
 					assert.Equal(mc, thingID, req.ThingID)
@@ -185,10 +185,11 @@ func Test_AddThingNotificationHandler(t *testing.T) {
 
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			fiberApp := fiber.New()
-			serviceProvider := sp.InitMock(tt.repoMock(mc))
+			t.Parallel()
 
-			fiberApp.Post("/v1/things/notifications", AddThingNotificationHandler(serviceProvider))
+			mc := minimock.NewController(t)
+			fiberApp := fiber.New()
+			fiberApp.Post("/v1/things/notifications", AddThingNotificationHandler(tt.repoMock(mc)))
 
 			fiberReq := httptest.NewRequest(tt.req.method, tt.req.route, helpers.ConvertDataToIOReader(tt.req.body))
 			fiberReq.Header.Add(fiber.HeaderContentType, tt.req.contentType)

+ 9 - 6
internal/api/v1/notification/delete_thing_notification.go

@@ -2,10 +2,11 @@ package notification
 
 import (
 	"database/sql"
+	"errors"
 
-	"git.dmitriygnatenko.ru/dima/homethings/internal/factory"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
 	"github.com/gofiber/fiber/v2"
+
+	"git.dmitriygnatenko.ru/dima/homethings/internal/factory"
 )
 
 // @Router 		/api/v1/things/notifications/{thingId} [delete]
@@ -18,7 +19,9 @@ import (
 // @security 	APIKey
 // @Accept      json
 // @Produce     json
-func DeleteThingNotificationHandler(sp interfaces.ServiceProvider) fiber.Handler {
+func DeleteThingNotificationHandler(
+	thingNotificationRepository ThingNotificationRepository,
+) fiber.Handler {
 	return func(fctx *fiber.Ctx) error {
 		ctx := fctx.Context()
 		id, err := fctx.ParamsInt("thingId")
@@ -26,16 +29,16 @@ func DeleteThingNotificationHandler(sp interfaces.ServiceProvider) fiber.Handler
 			return fiber.NewError(fiber.StatusBadRequest, err.Error())
 		}
 
-		_, err = sp.GetThingNotificationRepository().Get(ctx, id)
+		_, err = thingNotificationRepository.Get(ctx, id)
 		if err != nil {
-			if err == sql.ErrNoRows {
+			if errors.Is(err, sql.ErrNoRows) {
 				return fiber.NewError(fiber.StatusBadRequest, "")
 			}
 
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
-		if err = sp.GetThingNotificationRepository().Delete(ctx, id, nil); err != nil {
+		if err = thingNotificationRepository.Delete(ctx, id, nil); err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 

+ 22 - 21
internal/api/v1/notification/delete_thing_notification_test.go

@@ -9,19 +9,20 @@ import (
 	"testing"
 	"time"
 
-	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
-	repoMocks "git.dmitriygnatenko.ru/dima/homethings/internal/repositories/mocks"
-	sp "git.dmitriygnatenko.ru/dima/homethings/internal/service_provider"
 	"github.com/brianvoe/gofakeit/v6"
 	"github.com/gofiber/fiber/v2"
 	"github.com/gojuno/minimock/v3"
 	"github.com/stretchr/testify/assert"
+
+	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/notification/mocks"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
 )
 
 func Test_DeleteThingNotificationHandler(t *testing.T) {
+	t.Parallel()
+
 	type req struct {
 		method      string
 		route       string
@@ -29,7 +30,6 @@ func Test_DeleteThingNotificationHandler(t *testing.T) {
 	}
 
 	var (
-		mc        = minimock.NewController(t)
 		thingID   = gofakeit.Number(1, 1000)
 		testError = errors.New(gofakeit.Phrase())
 
@@ -52,14 +52,14 @@ func Test_DeleteThingNotificationHandler(t *testing.T) {
 		req      req
 		resCode  int
 		resBody  interface{}
-		repoMock func(mc *minimock.Controller) interfaces.ThingNotificationRepository
+		repoMock func(mc *minimock.Controller) ThingNotificationRepository
 	}{
 		{
 			name:    "positive case",
 			req:     correctReq,
 			resCode: fiber.StatusOK,
-			repoMock: func(mc *minimock.Controller) interfaces.ThingNotificationRepository {
-				mock := repoMocks.NewThingNotificationRepositoryMock(mc)
+			repoMock: func(mc *minimock.Controller) ThingNotificationRepository {
+				mock := mocks.NewThingNotificationRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -80,16 +80,16 @@ func Test_DeleteThingNotificationHandler(t *testing.T) {
 				contentType: fiber.MIMEApplicationJSON,
 			},
 			resCode: fiber.StatusBadRequest,
-			repoMock: func(mc *minimock.Controller) interfaces.ThingNotificationRepository {
-				return repoMocks.NewThingNotificationRepositoryMock(mc)
+			repoMock: func(mc *minimock.Controller) ThingNotificationRepository {
+				return mocks.NewThingNotificationRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - repository error (get)",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			repoMock: func(mc *minimock.Controller) interfaces.ThingNotificationRepository {
-				mock := repoMocks.NewThingNotificationRepositoryMock(mc)
+			repoMock: func(mc *minimock.Controller) ThingNotificationRepository {
+				mock := mocks.NewThingNotificationRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -102,8 +102,8 @@ func Test_DeleteThingNotificationHandler(t *testing.T) {
 			name:    "negative case - bad request (notification not found)",
 			req:     correctReq,
 			resCode: fiber.StatusBadRequest,
-			repoMock: func(mc *minimock.Controller) interfaces.ThingNotificationRepository {
-				mock := repoMocks.NewThingNotificationRepositoryMock(mc)
+			repoMock: func(mc *minimock.Controller) ThingNotificationRepository {
+				mock := mocks.NewThingNotificationRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -116,8 +116,8 @@ func Test_DeleteThingNotificationHandler(t *testing.T) {
 			name:    "negative case - repository error (delete)",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			repoMock: func(mc *minimock.Controller) interfaces.ThingNotificationRepository {
-				mock := repoMocks.NewThingNotificationRepositoryMock(mc)
+			repoMock: func(mc *minimock.Controller) ThingNotificationRepository {
+				mock := mocks.NewThingNotificationRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -134,10 +134,11 @@ func Test_DeleteThingNotificationHandler(t *testing.T) {
 
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			fiberApp := fiber.New()
-			serviceProvider := sp.InitMock(tt.repoMock(mc))
+			t.Parallel()
 
-			fiberApp.Delete("/v1/things/notifications/:thingId", DeleteThingNotificationHandler(serviceProvider))
+			mc := minimock.NewController(t)
+			fiberApp := fiber.New()
+			fiberApp.Delete("/v1/things/notifications/:thingId", DeleteThingNotificationHandler(tt.repoMock(mc)))
 
 			fiberReq := httptest.NewRequest(tt.req.method, tt.req.route, nil)
 			fiberReq.Header.Add(fiber.HeaderContentType, tt.req.contentType)

+ 7 - 5
internal/api/v1/notification/get_expired_thing_notifications.go

@@ -1,10 +1,10 @@
 package notification
 
 import (
+	"github.com/gofiber/fiber/v2"
+
 	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/mappers"
-	"github.com/gofiber/fiber/v2"
 )
 
 // @Router 		/api/v1/things/notifications/expired [get]
@@ -16,15 +16,17 @@ import (
 // @security 	APIKey
 // @Accept      json
 // @Produce     json
-func GetExpiredThingNotificationsHandler(sp interfaces.ServiceProvider) fiber.Handler {
+func GetExpiredThingNotificationsHandler(
+	thingNotificationRepository ThingNotificationRepository,
+) fiber.Handler {
 	return func(fctx *fiber.Ctx) error {
-		res, err := sp.GetThingNotificationRepository().GetExpired(fctx.Context())
+		res, err := thingNotificationRepository.GetExpired(fctx.Context())
 		if err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
 		res = helpers.ApplyLocation(fctx, res)
 
-		return fctx.JSON(mappers.ConvertToThingNotificationsExtResponseDTO(res))
+		return fctx.JSON(mappers.ToThingNotificationsExtResponse(res))
 	}
 }

+ 18 - 17
internal/api/v1/notification/get_expired_thing_notifications_test.go

@@ -6,27 +6,27 @@ import (
 	"testing"
 	"time"
 
-	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
-	repoMocks "git.dmitriygnatenko.ru/dima/homethings/internal/repositories/mocks"
-	sp "git.dmitriygnatenko.ru/dima/homethings/internal/service_provider"
 	"github.com/brianvoe/gofakeit/v6"
 	"github.com/gofiber/fiber/v2"
 	"github.com/gojuno/minimock/v3"
 	"github.com/stretchr/testify/assert"
+
+	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/notification/mocks"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
 )
 
-func Test_GetExpiredThingNotificationsHandler(t *testing.T) {
+func TestGetExpiredThingNotificationsHandler(t *testing.T) {
+	t.Parallel()
+
 	type req struct {
 		method string
 		route  string
 	}
 
 	var (
-		mc        = minimock.NewController(t)
 		testError = errors.New(gofakeit.Phrase())
 		layout    = "2006-01-02 15:04:05"
 
@@ -67,15 +67,15 @@ func Test_GetExpiredThingNotificationsHandler(t *testing.T) {
 		req      req
 		resCode  int
 		resBody  interface{}
-		repoMock func(mc *minimock.Controller) interfaces.ThingNotificationRepository
+		repoMock func(mc *minimock.Controller) ThingNotificationRepository
 	}{
 		{
 			name:    "positive case",
 			req:     correctReq,
 			resCode: fiber.StatusOK,
 			resBody: expectedRes,
-			repoMock: func(mc *minimock.Controller) interfaces.ThingNotificationRepository {
-				mock := repoMocks.NewThingNotificationRepositoryMock(mc)
+			repoMock: func(mc *minimock.Controller) ThingNotificationRepository {
+				mock := mocks.NewThingNotificationRepositoryMock(mc)
 				mock.GetExpiredMock.Return(repoRes, nil)
 				return mock
 			},
@@ -84,8 +84,8 @@ func Test_GetExpiredThingNotificationsHandler(t *testing.T) {
 			name:    "negative case - repository error",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			repoMock: func(mc *minimock.Controller) interfaces.ThingNotificationRepository {
-				mock := repoMocks.NewThingNotificationRepositoryMock(mc)
+			repoMock: func(mc *minimock.Controller) ThingNotificationRepository {
+				mock := mocks.NewThingNotificationRepositoryMock(mc)
 				mock.GetExpiredMock.Return(nil, testError)
 				return mock
 			},
@@ -94,10 +94,11 @@ func Test_GetExpiredThingNotificationsHandler(t *testing.T) {
 
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			fiberApp := fiber.New()
-			serviceProvider := sp.InitMock(tt.repoMock(mc))
+			t.Parallel()
 
-			fiberApp.Get("/v1/things/notifications/expired", GetExpiredThingNotificationsHandler(serviceProvider))
+			mc := minimock.NewController(t)
+			fiberApp := fiber.New()
+			fiberApp.Get("/v1/things/notifications/expired", GetExpiredThingNotificationsHandler(tt.repoMock(mc)))
 
 			fiberRes, _ := fiberApp.Test(httptest.NewRequest(tt.req.method, tt.req.route, nil), API.DefaultTestTimeOut)
 			assert.Equal(t, tt.resCode, fiberRes.StatusCode)

+ 9 - 6
internal/api/v1/notification/get_thing_notification.go

@@ -2,11 +2,12 @@ package notification
 
 import (
 	"database/sql"
+	"errors"
+
+	"github.com/gofiber/fiber/v2"
 
 	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/mappers"
-	"github.com/gofiber/fiber/v2"
 )
 
 // @Router 		/api/v1/things/notifications/{thingId} [get]
@@ -20,7 +21,9 @@ import (
 // @security 	APIKey
 // @Accept      json
 // @Produce     json
-func GetThingNotificationHandler(sp interfaces.ServiceProvider) fiber.Handler {
+func GetThingNotificationHandler(
+	thingNotificationRepository ThingNotificationRepository,
+) fiber.Handler {
 	return func(fctx *fiber.Ctx) error {
 		ctx := fctx.Context()
 		id, err := fctx.ParamsInt("thingId")
@@ -28,9 +31,9 @@ func GetThingNotificationHandler(sp interfaces.ServiceProvider) fiber.Handler {
 			return fiber.NewError(fiber.StatusBadRequest, err.Error())
 		}
 
-		res, err := sp.GetThingNotificationRepository().Get(ctx, id)
+		res, err := thingNotificationRepository.Get(ctx, id)
 		if err != nil {
-			if err == sql.ErrNoRows {
+			if errors.Is(err, sql.ErrNoRows) {
 				return fiber.NewError(fiber.StatusNotFound, "")
 			}
 
@@ -39,6 +42,6 @@ func GetThingNotificationHandler(sp interfaces.ServiceProvider) fiber.Handler {
 
 		res = helpers.ApplyLocation(fctx, res)
 
-		return fctx.JSON(mappers.ConvertToThingNotificationResponseDTO(*res))
+		return fctx.JSON(mappers.ToThingNotificationResponse(*res))
 	}
 }

+ 22 - 21
internal/api/v1/notification/get_thing_notification_test.go

@@ -9,27 +9,27 @@ import (
 	"testing"
 	"time"
 
-	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
-	repoMocks "git.dmitriygnatenko.ru/dima/homethings/internal/repositories/mocks"
-	sp "git.dmitriygnatenko.ru/dima/homethings/internal/service_provider"
 	"github.com/brianvoe/gofakeit/v6"
 	"github.com/gofiber/fiber/v2"
 	"github.com/gojuno/minimock/v3"
 	"github.com/stretchr/testify/assert"
+
+	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/notification/mocks"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
 )
 
-func Test_GetThingNotificationHandler(t *testing.T) {
+func TestGetThingNotificationHandler(t *testing.T) {
+	t.Parallel()
+
 	type req struct {
 		method string
 		route  string
 	}
 
 	var (
-		mc        = minimock.NewController(t)
 		thingID   = gofakeit.Number(1, 1000)
 		testError = errors.New(gofakeit.Phrase())
 		layout    = "2006-01-02 15:04:05"
@@ -59,15 +59,15 @@ func Test_GetThingNotificationHandler(t *testing.T) {
 		req      req
 		resCode  int
 		resBody  interface{}
-		repoMock func(mc *minimock.Controller) interfaces.ThingNotificationRepository
+		repoMock func(mc *minimock.Controller) ThingNotificationRepository
 	}{
 		{
 			name:    "positive case",
 			req:     correctReq,
 			resCode: fiber.StatusOK,
 			resBody: expectedRes,
-			repoMock: func(mc *minimock.Controller) interfaces.ThingNotificationRepository {
-				mock := repoMocks.NewThingNotificationRepositoryMock(mc)
+			repoMock: func(mc *minimock.Controller) ThingNotificationRepository {
+				mock := mocks.NewThingNotificationRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -80,8 +80,8 @@ func Test_GetThingNotificationHandler(t *testing.T) {
 			name:    "negative case - repository error",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			repoMock: func(mc *minimock.Controller) interfaces.ThingNotificationRepository {
-				mock := repoMocks.NewThingNotificationRepositoryMock(mc)
+			repoMock: func(mc *minimock.Controller) ThingNotificationRepository {
+				mock := mocks.NewThingNotificationRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -94,8 +94,8 @@ func Test_GetThingNotificationHandler(t *testing.T) {
 			name:    "negative case - not found",
 			req:     correctReq,
 			resCode: fiber.StatusNotFound,
-			repoMock: func(mc *minimock.Controller) interfaces.ThingNotificationRepository {
-				mock := repoMocks.NewThingNotificationRepositoryMock(mc)
+			repoMock: func(mc *minimock.Controller) ThingNotificationRepository {
+				mock := mocks.NewThingNotificationRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -111,18 +111,19 @@ func Test_GetThingNotificationHandler(t *testing.T) {
 				route:  "/v1/things/notifications/" + gofakeit.Word(),
 			},
 			resCode: fiber.StatusBadRequest,
-			repoMock: func(mc *minimock.Controller) interfaces.ThingNotificationRepository {
-				return repoMocks.NewThingNotificationRepositoryMock(mc)
+			repoMock: func(mc *minimock.Controller) ThingNotificationRepository {
+				return mocks.NewThingNotificationRepositoryMock(mc)
 			},
 		},
 	}
 
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			fiberApp := fiber.New()
-			serviceProvider := sp.InitMock(tt.repoMock(mc))
+			t.Parallel()
 
-			fiberApp.Get("/v1/things/notifications/:thingId", GetThingNotificationHandler(serviceProvider))
+			mc := minimock.NewController(t)
+			fiberApp := fiber.New()
+			fiberApp.Get("/v1/things/notifications/:thingId", GetThingNotificationHandler(tt.repoMock(mc)))
 
 			fiberRes, _ := fiberApp.Test(httptest.NewRequest(tt.req.method, tt.req.route, nil), API.DefaultTestTimeOut)
 			assert.Equal(t, tt.resCode, fiberRes.StatusCode)

File diff ditekan karena terlalu besar
+ 513 - 78
internal/api/v1/notification/mocks/thing_notification_repository_minimock.go


+ 11 - 9
internal/api/v1/notification/update_thing_notification.go

@@ -3,13 +3,13 @@ package notification
 import (
 	"database/sql"
 
+	"github.com/go-playground/validator/v10"
+	"github.com/gofiber/fiber/v2"
+
 	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/factory"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/mappers"
-	"github.com/go-playground/validator/v10"
-	"github.com/gofiber/fiber/v2"
 )
 
 // @Router 		/api/v1/things/notifications/{thingId} [put]
@@ -23,7 +23,9 @@ import (
 // @security 	APIKey
 // @Accept      json
 // @Produce     json
-func UpdateThingNotificationHandler(sp interfaces.ServiceProvider) fiber.Handler {
+func UpdateThingNotificationHandler(
+	thingNotificationRepository ThingNotificationRepository,
+) fiber.Handler {
 	return func(fctx *fiber.Ctx) error {
 		ctx := fctx.Context()
 		id, err := fctx.ParamsInt("thingId")
@@ -41,7 +43,7 @@ func UpdateThingNotificationHandler(sp interfaces.ServiceProvider) fiber.Handler
 			return fctx.Status(fiber.StatusBadRequest).JSON(factory.CreateValidateErrorResponse(err))
 		}
 
-		_, err = sp.GetThingNotificationRepository().Get(ctx, id)
+		_, err = thingNotificationRepository.Get(ctx, id)
 		if err != nil {
 			if err == sql.ErrNoRows {
 				return fiber.NewError(fiber.StatusBadRequest, "")
@@ -50,22 +52,22 @@ func UpdateThingNotificationHandler(sp interfaces.ServiceProvider) fiber.Handler
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
-		dbReq, err := mappers.ConvertToUpdateThingNotificationRequestModel(id, req)
+		dbReq, err := mappers.ToUpdateThingNotificationRequest(id, req)
 		if err != nil {
 			return fiber.NewError(fiber.StatusBadRequest, err.Error())
 		}
 
-		if err = sp.GetThingNotificationRepository().Update(ctx, *dbReq, nil); err != nil {
+		if err = thingNotificationRepository.Update(ctx, *dbReq, nil); err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
-		res, err := sp.GetThingNotificationRepository().Get(ctx, id)
+		res, err := thingNotificationRepository.Get(ctx, id)
 		if err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
 		res = helpers.ApplyLocation(fctx, res)
 
-		return fctx.JSON(mappers.ConvertToThingNotificationResponseDTO(*res))
+		return fctx.JSON(mappers.ToThingNotificationResponse(*res))
 	}
 }

+ 32 - 31
internal/api/v1/notification/update_thing_notification_test.go

@@ -9,20 +9,21 @@ import (
 	"testing"
 	"time"
 
-	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
-	repoMocks "git.dmitriygnatenko.ru/dima/homethings/internal/repositories/mocks"
-	sp "git.dmitriygnatenko.ru/dima/homethings/internal/service_provider"
 	"github.com/brianvoe/gofakeit/v6"
 	"github.com/gofiber/fiber/v2"
 	"github.com/gojuno/minimock/v3"
 	"github.com/stretchr/testify/assert"
+
+	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/notification/mocks"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
 )
 
-func Test_UpdateThingNotificationHandler(t *testing.T) {
+func TestUpdateThingNotificationHandler(t *testing.T) {
+	t.Parallel()
+
 	type req struct {
 		method      string
 		route       string
@@ -31,7 +32,6 @@ func Test_UpdateThingNotificationHandler(t *testing.T) {
 	}
 
 	var (
-		mc               = minimock.NewController(t)
 		thingID          = gofakeit.Number(1, 1000)
 		notificationDate = gofakeit.Date().Truncate(time.Second)
 		testError        = errors.New(gofakeit.Phrase())
@@ -66,15 +66,15 @@ func Test_UpdateThingNotificationHandler(t *testing.T) {
 		req      req
 		resCode  int
 		resBody  interface{}
-		repoMock func(mc *minimock.Controller) interfaces.ThingNotificationRepository
+		repoMock func(mc *minimock.Controller) ThingNotificationRepository
 	}{
 		{
 			name:    "positive case",
 			req:     correctReq,
 			resCode: fiber.StatusOK,
 			resBody: expectedRes,
-			repoMock: func(mc *minimock.Controller) interfaces.ThingNotificationRepository {
-				mock := repoMocks.NewThingNotificationRepositoryMock(mc)
+			repoMock: func(mc *minimock.Controller) ThingNotificationRepository {
+				mock := mocks.NewThingNotificationRepositoryMock(mc)
 
 				mock.UpdateMock.Inspect(func(ctx context.Context, req models.UpdateThingNotificationRequest, tx *sql.Tx) {
 					assert.Equal(mc, thingID, req.ThingID)
@@ -99,8 +99,8 @@ func Test_UpdateThingNotificationHandler(t *testing.T) {
 				route:  "/v1/things/notifications/" + gofakeit.Word(),
 			},
 			resCode: fiber.StatusBadRequest,
-			repoMock: func(mc *minimock.Controller) interfaces.ThingNotificationRepository {
-				return repoMocks.NewThingNotificationRepositoryMock(mc)
+			repoMock: func(mc *minimock.Controller) ThingNotificationRepository {
+				return mocks.NewThingNotificationRepositoryMock(mc)
 			},
 		},
 		{
@@ -110,8 +110,8 @@ func Test_UpdateThingNotificationHandler(t *testing.T) {
 				route:  "/v1/things/notifications/" + strconv.Itoa(thingID),
 			},
 			resCode: fiber.StatusBadRequest,
-			repoMock: func(mc *minimock.Controller) interfaces.ThingNotificationRepository {
-				return repoMocks.NewThingNotificationRepositoryMock(mc)
+			repoMock: func(mc *minimock.Controller) ThingNotificationRepository {
+				return mocks.NewThingNotificationRepositoryMock(mc)
 			},
 		},
 		{
@@ -122,16 +122,16 @@ func Test_UpdateThingNotificationHandler(t *testing.T) {
 				contentType: fiber.MIMEApplicationJSON,
 			},
 			resCode: fiber.StatusBadRequest,
-			repoMock: func(mc *minimock.Controller) interfaces.ThingNotificationRepository {
-				return repoMocks.NewThingNotificationRepositoryMock(mc)
+			repoMock: func(mc *minimock.Controller) ThingNotificationRepository {
+				return mocks.NewThingNotificationRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - repository error (get)",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			repoMock: func(mc *minimock.Controller) interfaces.ThingNotificationRepository {
-				mock := repoMocks.NewThingNotificationRepositoryMock(mc)
+			repoMock: func(mc *minimock.Controller) ThingNotificationRepository {
+				mock := mocks.NewThingNotificationRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -144,8 +144,8 @@ func Test_UpdateThingNotificationHandler(t *testing.T) {
 			name:    "negative case - bad request (notification not found)",
 			req:     correctReq,
 			resCode: fiber.StatusBadRequest,
-			repoMock: func(mc *minimock.Controller) interfaces.ThingNotificationRepository {
-				mock := repoMocks.NewThingNotificationRepositoryMock(mc)
+			repoMock: func(mc *minimock.Controller) ThingNotificationRepository {
+				mock := mocks.NewThingNotificationRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -165,8 +165,8 @@ func Test_UpdateThingNotificationHandler(t *testing.T) {
 				contentType: fiber.MIMEApplicationJSON,
 			},
 			resCode: fiber.StatusBadRequest,
-			repoMock: func(mc *minimock.Controller) interfaces.ThingNotificationRepository {
-				mock := repoMocks.NewThingNotificationRepositoryMock(mc)
+			repoMock: func(mc *minimock.Controller) ThingNotificationRepository {
+				mock := mocks.NewThingNotificationRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -179,8 +179,8 @@ func Test_UpdateThingNotificationHandler(t *testing.T) {
 			name:    "negative case - repository error (update)",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			repoMock: func(mc *minimock.Controller) interfaces.ThingNotificationRepository {
-				mock := repoMocks.NewThingNotificationRepositoryMock(mc)
+			repoMock: func(mc *minimock.Controller) ThingNotificationRepository {
+				mock := mocks.NewThingNotificationRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -198,8 +198,8 @@ func Test_UpdateThingNotificationHandler(t *testing.T) {
 			name:    "negative case - repository error (get)",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			repoMock: func(mc *minimock.Controller) interfaces.ThingNotificationRepository {
-				mock := repoMocks.NewThingNotificationRepositoryMock(mc)
+			repoMock: func(mc *minimock.Controller) ThingNotificationRepository {
+				mock := mocks.NewThingNotificationRepositoryMock(mc)
 
 				mock.UpdateMock.Inspect(func(ctx context.Context, req models.UpdateThingNotificationRequest, tx *sql.Tx) {
 					assert.Equal(mc, thingID, req.ThingID)
@@ -221,10 +221,11 @@ func Test_UpdateThingNotificationHandler(t *testing.T) {
 
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			fiberApp := fiber.New()
-			serviceProvider := sp.InitMock(tt.repoMock(mc))
+			t.Parallel()
 
-			fiberApp.Put("/v1/things/notifications/:thingId", UpdateThingNotificationHandler(serviceProvider))
+			mc := minimock.NewController(t)
+			fiberApp := fiber.New()
+			fiberApp.Put("/v1/things/notifications/:thingId", UpdateThingNotificationHandler(tt.repoMock(mc)))
 
 			fiberReq := httptest.NewRequest(tt.req.method, tt.req.route, helpers.ConvertDataToIOReader(tt.req.body))
 			fiberReq.Header.Add(fiber.HeaderContentType, tt.req.contentType)

+ 61 - 7
internal/api/v1/place/add_place.go

@@ -1,13 +1,65 @@
 package place
 
+//go:generate mkdir -p mocks
+//go:generate rm -rf ./mocks/*_minimock.go
+//go:generate minimock -i PlaceRepository,ThingRepository,PlaceImageRepository,ThingImageRepository,PlaceThingRepository,ThingTagRepository,ThingNotificationRepository,FileRepository -o ./mocks/ -s "_minimock.go"
+
 import (
+	"context"
+	"database/sql"
+
+	"github.com/go-playground/validator/v10"
+	"github.com/gofiber/fiber/v2"
+
 	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/factory"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/mappers"
-	"github.com/go-playground/validator/v10"
-	"github.com/gofiber/fiber/v2"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
+)
+
+type (
+	PlaceRepository interface {
+		GetAll(ctx context.Context) ([]models.Place, error)
+		Get(ctx context.Context, placeID int) (*models.Place, error)
+		GetNestedPlaces(ctx context.Context, placeID int) ([]models.Place, error)
+		Add(ctx context.Context, req models.AddPlaceRequest, tx *sql.Tx) (int, error)
+		Update(ctx context.Context, req models.UpdatePlaceRequest, tx *sql.Tx) error
+		Delete(ctx context.Context, placeID int, tx *sql.Tx) error
+		BeginTx(ctx context.Context, level sql.IsolationLevel) (*sql.Tx, error)
+		CommitTx(tx *sql.Tx) error
+	}
+
+	ThingRepository interface {
+		GetByPlaceID(ctx context.Context, placeID int) ([]models.Thing, error)
+		Delete(ctx context.Context, thingID int, tx *sql.Tx) error
+	}
+
+	PlaceImageRepository interface {
+		GetByPlaceID(ctx context.Context, placeID int) ([]models.Image, error)
+		Delete(ctx context.Context, imageID int, tx *sql.Tx) error
+	}
+
+	ThingImageRepository interface {
+		GetByThingID(ctx context.Context, thingID int) ([]models.Image, error)
+		Delete(ctx context.Context, imageID int, tx *sql.Tx) error
+	}
+
+	PlaceThingRepository interface {
+		DeleteThing(ctx context.Context, thingID int, tx *sql.Tx) error
+	}
+
+	ThingTagRepository interface {
+		DeleteByThingID(ctx context.Context, thingID int, tx *sql.Tx) error
+	}
+
+	ThingNotificationRepository interface {
+		Delete(ctx context.Context, thingID int, tx *sql.Tx) error
+	}
+
+	FileRepository interface {
+		Delete(path string) error
+	}
 )
 
 // @Router 		/api/v1/places [post]
@@ -20,7 +72,9 @@ import (
 // @security 	APIKey
 // @Accept      json
 // @Produce     json
-func AddPlaceHandler(sp interfaces.ServiceProvider) fiber.Handler {
+func AddPlaceHandler(
+	placeRepository PlaceRepository,
+) fiber.Handler {
 	return func(fctx *fiber.Ctx) error {
 		ctx := fctx.Context()
 		req := dto.AddPlaceRequest{}
@@ -33,18 +87,18 @@ func AddPlaceHandler(sp interfaces.ServiceProvider) fiber.Handler {
 			return fctx.Status(fiber.StatusBadRequest).JSON(factory.CreateValidateErrorResponse(err))
 		}
 
-		id, err := sp.GetPlaceRepository().Add(ctx, mappers.ConvertToAddPlaceRequestModel(req), nil)
+		id, err := placeRepository.Add(ctx, mappers.ToAddPlaceRequest(req), nil)
 		if err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
-		res, err := sp.GetPlaceRepository().Get(ctx, id)
+		res, err := placeRepository.Get(ctx, id)
 		if err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
 		res = helpers.ApplyLocation(fctx, res)
 
-		return fctx.JSON(mappers.ConvertToPlaceResponseDTO(*res))
+		return fctx.JSON(mappers.ToPlaceResponse(*res))
 	}
 }

+ 24 - 23
internal/api/v1/place/add_place_test.go

@@ -7,20 +7,21 @@ import (
 	"net/http/httptest"
 	"testing"
 
-	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
-	repoMocks "git.dmitriygnatenko.ru/dima/homethings/internal/repositories/mocks"
-	sp "git.dmitriygnatenko.ru/dima/homethings/internal/service_provider"
 	"github.com/brianvoe/gofakeit/v6"
 	"github.com/gofiber/fiber/v2"
 	"github.com/gojuno/minimock/v3"
 	"github.com/stretchr/testify/assert"
+
+	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/place/mocks"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
 )
 
-func Test_AddPlaceHandler(t *testing.T) {
+func TestAddPlaceHandler(t *testing.T) {
+	t.Parallel()
+
 	type req struct {
 		method      string
 		route       string
@@ -29,7 +30,6 @@ func Test_AddPlaceHandler(t *testing.T) {
 	}
 
 	var (
-		mc        = minimock.NewController(t)
 		placeID   = gofakeit.Number(1, 1000)
 		parentID  = gofakeit.Number(1, 1000)
 		title     = gofakeit.Phrase()
@@ -68,15 +68,15 @@ func Test_AddPlaceHandler(t *testing.T) {
 		req           req
 		resCode       int
 		resBody       interface{}
-		placeRepoMock func(mc *minimock.Controller) interfaces.PlaceRepository
+		placeRepoMock func(mc *minimock.Controller) PlaceRepository
 	}{
 		{
 			name:    "positive case",
 			req:     correctReq,
 			resCode: fiber.StatusOK,
 			resBody: expectedRes,
-			placeRepoMock: func(mc *minimock.Controller) interfaces.PlaceRepository {
-				mock := repoMocks.NewPlaceRepositoryMock(mc)
+			placeRepoMock: func(mc *minimock.Controller) PlaceRepository {
+				mock := mocks.NewPlaceRepositoryMock(mc)
 
 				mock.AddMock.Inspect(func(ctx context.Context, req models.AddPlaceRequest, tx *sql.Tx) {
 					assert.Equal(mc, title, req.Title)
@@ -97,8 +97,8 @@ func Test_AddPlaceHandler(t *testing.T) {
 				route:  "/v1/places",
 			},
 			resCode: fiber.StatusBadRequest,
-			placeRepoMock: func(mc *minimock.Controller) interfaces.PlaceRepository {
-				return repoMocks.NewPlaceRepositoryMock(mc)
+			placeRepoMock: func(mc *minimock.Controller) PlaceRepository {
+				return mocks.NewPlaceRepositoryMock(mc)
 			},
 		},
 		{
@@ -116,16 +116,16 @@ func Test_AddPlaceHandler(t *testing.T) {
 					Tag:   "required",
 				},
 			},
-			placeRepoMock: func(mc *minimock.Controller) interfaces.PlaceRepository {
-				return repoMocks.NewPlaceRepositoryMock(mc)
+			placeRepoMock: func(mc *minimock.Controller) PlaceRepository {
+				return mocks.NewPlaceRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - repository error (add place)",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			placeRepoMock: func(mc *minimock.Controller) interfaces.PlaceRepository {
-				mock := repoMocks.NewPlaceRepositoryMock(mc)
+			placeRepoMock: func(mc *minimock.Controller) PlaceRepository {
+				mock := mocks.NewPlaceRepositoryMock(mc)
 
 				mock.AddMock.Inspect(func(ctx context.Context, req models.AddPlaceRequest, tx *sql.Tx) {
 					assert.Equal(mc, title, req.Title)
@@ -139,8 +139,8 @@ func Test_AddPlaceHandler(t *testing.T) {
 			name:    "negative case - repository error (get place)",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			placeRepoMock: func(mc *minimock.Controller) interfaces.PlaceRepository {
-				mock := repoMocks.NewPlaceRepositoryMock(mc)
+			placeRepoMock: func(mc *minimock.Controller) PlaceRepository {
+				mock := mocks.NewPlaceRepositoryMock(mc)
 
 				mock.AddMock.Inspect(func(ctx context.Context, req models.AddPlaceRequest, tx *sql.Tx) {
 					assert.Equal(mc, title, req.Title)
@@ -158,10 +158,11 @@ func Test_AddPlaceHandler(t *testing.T) {
 
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			fiberApp := fiber.New()
-			serviceProvider := sp.InitMock(tt.placeRepoMock(mc))
+			t.Parallel()
 
-			fiberApp.Post("/v1/places", AddPlaceHandler(serviceProvider))
+			mc := minimock.NewController(t)
+			fiberApp := fiber.New()
+			fiberApp.Post("/v1/places", AddPlaceHandler(tt.placeRepoMock(mc)))
 
 			fiberReq := httptest.NewRequest(tt.req.method, tt.req.route, helpers.ConvertDataToIOReader(tt.req.body))
 			fiberReq.Header.Add(fiber.HeaderContentType, tt.req.contentType)

+ 29 - 22
internal/api/v1/place/delete_place.go

@@ -3,11 +3,11 @@ package place
 import (
 	"database/sql"
 
+	"github.com/gofiber/fiber/v2"
+
 	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/factory"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
-	"github.com/gofiber/fiber/v2"
 )
 
 // @Router 		/api/v1/places/{placeId} [delete]
@@ -20,7 +20,16 @@ import (
 // @security 	APIKey
 // @Accept      json
 // @Produce     json
-func DeletePlaceHandler(sp interfaces.ServiceProvider) fiber.Handler {
+func DeletePlaceHandler(
+	placeRepository PlaceRepository,
+	thingRepository ThingRepository,
+	placeImageRepository PlaceImageRepository,
+	thingImageRepository ThingImageRepository,
+	placeThingRepository PlaceThingRepository,
+	thingTagRepository ThingTagRepository,
+	thingNotificationRepository ThingNotificationRepository,
+	fileRepository FileRepository,
+) fiber.Handler {
 	return func(fctx *fiber.Ctx) error {
 		ctx := fctx.Context()
 		id, err := fctx.ParamsInt("placeId")
@@ -28,7 +37,7 @@ func DeletePlaceHandler(sp interfaces.ServiceProvider) fiber.Handler {
 			return fiber.NewError(fiber.StatusBadRequest, err.Error())
 		}
 
-		_, err = sp.GetPlaceRepository().Get(ctx, id)
+		_, err = placeRepository.Get(ctx, id)
 		if err != nil {
 			if err == sql.ErrNoRows {
 				return fiber.NewError(fiber.StatusBadRequest, "")
@@ -37,7 +46,7 @@ func DeletePlaceHandler(sp interfaces.ServiceProvider) fiber.Handler {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
-		nestedRes, err := sp.GetPlaceRepository().GetNestedPlaces(ctx, id)
+		nestedRes, err := placeRepository.GetNestedPlaces(ctx, id)
 		if err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
@@ -46,12 +55,12 @@ func DeletePlaceHandler(sp interfaces.ServiceProvider) fiber.Handler {
 			return fiber.NewError(fiber.StatusBadRequest, "")
 		}
 
-		placeImages, err := sp.GetPlaceImageRepository().GetByPlaceID(ctx, id)
+		placeImages, err := placeImageRepository.GetByPlaceID(ctx, id)
 		if err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
-		things, err := sp.GetThingRepository().GetByPlaceID(ctx, id)
+		things, err := thingRepository.GetByPlaceID(ctx, id)
 		if err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
@@ -62,17 +71,15 @@ func DeletePlaceHandler(sp interfaces.ServiceProvider) fiber.Handler {
 		for _, thing := range things {
 			thingIDs = append(thingIDs, thing.ID)
 
-			thingImagesRes, thingImagesErr := sp.GetThingImageRepository().GetByThingID(ctx, thing.ID)
+			thingImagesRes, thingImagesErr := thingImageRepository.GetByThingID(ctx, thing.ID)
 			if thingImagesErr != nil {
 				return fiber.NewError(fiber.StatusInternalServerError, thingImagesErr.Error())
 			}
 
-			for i := range thingImagesRes {
-				thingImages = append(thingImages, thingImagesRes[i])
-			}
+			thingImages = append(thingImages, thingImagesRes...)
 		}
 
-		tx, err := sp.GetPlaceRepository().BeginTx(ctx, API.DefaultTxLevel)
+		tx, err := placeRepository.BeginTx(ctx, API.DefaultTxLevel)
 		if err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
@@ -81,53 +88,53 @@ func DeletePlaceHandler(sp interfaces.ServiceProvider) fiber.Handler {
 		for i := range placeImages {
 			placeImageURLs = append(placeImageURLs, placeImages[i].Image)
 
-			if err = sp.GetPlaceImageRepository().Delete(ctx, placeImages[i].ID, tx); err != nil {
+			if err = placeImageRepository.Delete(ctx, placeImages[i].ID, tx); err != nil {
 				return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 			}
 		}
 
 		for i := range thingImages {
-			if err = sp.GetThingImageRepository().Delete(ctx, thingImages[i].ID, tx); err != nil {
+			if err = thingImageRepository.Delete(ctx, thingImages[i].ID, tx); err != nil {
 				return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 			}
 		}
 
 		for _, thingID := range thingIDs {
-			if err = sp.GetPlaceThingRepository().DeleteThing(ctx, thingID, tx); err != nil {
+			if err = placeThingRepository.DeleteThing(ctx, thingID, tx); err != nil {
 				return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 			}
 
-			if err = sp.GetThingTagRepository().DeleteByThingID(ctx, thingID, tx); err != nil {
+			if err = thingTagRepository.DeleteByThingID(ctx, thingID, tx); err != nil {
 				return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 			}
 
-			if err = sp.GetThingNotificationRepository().Delete(ctx, thingID, tx); err != nil {
+			if err = thingNotificationRepository.Delete(ctx, thingID, tx); err != nil {
 				return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 			}
 
-			if err = sp.GetThingRepository().Delete(ctx, thingID, tx); err != nil {
+			if err = thingRepository.Delete(ctx, thingID, tx); err != nil {
 				return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 			}
 		}
 
-		if err = sp.GetPlaceRepository().Delete(ctx, id, tx); err != nil {
+		if err = placeRepository.Delete(ctx, id, tx); err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
-		if err = sp.GetPlaceRepository().CommitTx(tx); err != nil {
+		if err = placeRepository.CommitTx(tx); err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
 		if len(placeImageURLs) > 0 {
 			for i := range placeImageURLs {
-				if err = sp.GetFileRepository().Delete(placeImageURLs[i]); err != nil {
+				if err = fileRepository.Delete(placeImageURLs[i]); err != nil {
 					return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 				}
 			}
 		}
 
 		for i := range thingImages {
-			if err = sp.GetFileRepository().Delete(thingImages[i].Image); err != nil {
+			if err = fileRepository.Delete(thingImages[i].Image); err != nil {
 				return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 			}
 		}

File diff ditekan karena terlalu besar
+ 251 - 251
internal/api/v1/place/delete_place_test.go


+ 7 - 6
internal/api/v1/place/get_place.go

@@ -2,11 +2,12 @@ package place
 
 import (
 	"database/sql"
+	"errors"
+
+	"github.com/gofiber/fiber/v2"
 
 	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/mappers"
-	"github.com/gofiber/fiber/v2"
 )
 
 // @Router 		/api/v1/places/{placeId} [get]
@@ -20,7 +21,7 @@ import (
 // @security 	APIKey
 // @Accept      json
 // @Produce     json
-func GetPlaceHandler(sp interfaces.ServiceProvider) fiber.Handler {
+func GetPlaceHandler(placeRepository PlaceRepository) fiber.Handler {
 	return func(fctx *fiber.Ctx) error {
 		ctx := fctx.Context()
 		id, err := fctx.ParamsInt("placeId")
@@ -28,9 +29,9 @@ func GetPlaceHandler(sp interfaces.ServiceProvider) fiber.Handler {
 			return fiber.NewError(fiber.StatusBadRequest, err.Error())
 		}
 
-		res, err := sp.GetPlaceRepository().Get(ctx, id)
+		res, err := placeRepository.Get(ctx, id)
 		if err != nil {
-			if err == sql.ErrNoRows {
+			if errors.Is(err, sql.ErrNoRows) {
 				return fiber.NewError(fiber.StatusNotFound, "")
 			}
 
@@ -39,6 +40,6 @@ func GetPlaceHandler(sp interfaces.ServiceProvider) fiber.Handler {
 
 		res = helpers.ApplyLocation(fctx, res)
 
-		return fctx.JSON(mappers.ConvertToPlaceResponseDTO(*res))
+		return fctx.JSON(mappers.ToPlaceResponse(*res))
 	}
 }

+ 5 - 5
internal/api/v1/place/get_place_nested.go

@@ -1,10 +1,10 @@
 package place
 
 import (
+	"github.com/gofiber/fiber/v2"
+
 	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/mappers"
-	"github.com/gofiber/fiber/v2"
 )
 
 // @Router 		/api/v1/places/{parentPlaceId}/nested [get]
@@ -17,7 +17,7 @@ import (
 // @security 	APIKey
 // @Accept      json
 // @Produce     json
-func GetNestedPlacesHandler(sp interfaces.ServiceProvider) fiber.Handler {
+func GetNestedPlacesHandler(placeRepository PlaceRepository) fiber.Handler {
 	return func(fctx *fiber.Ctx) error {
 		ctx := fctx.Context()
 		id, err := fctx.ParamsInt("parentPlaceId")
@@ -25,13 +25,13 @@ func GetNestedPlacesHandler(sp interfaces.ServiceProvider) fiber.Handler {
 			return fiber.NewError(fiber.StatusBadRequest, err.Error())
 		}
 
-		res, err := sp.GetPlaceRepository().GetNestedPlaces(ctx, id)
+		res, err := placeRepository.GetNestedPlaces(ctx, id)
 		if err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
 		res = helpers.ApplyLocation(fctx, res)
 
-		return fctx.JSON(mappers.ConvertToPlacesResponseDTO(res))
+		return fctx.JSON(mappers.ToPlacesResponse(res))
 	}
 }

+ 20 - 19
internal/api/v1/place/get_place_nested_test.go

@@ -8,27 +8,27 @@ import (
 	"strconv"
 	"testing"
 
-	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
-	repoMocks "git.dmitriygnatenko.ru/dima/homethings/internal/repositories/mocks"
-	sp "git.dmitriygnatenko.ru/dima/homethings/internal/service_provider"
 	"github.com/brianvoe/gofakeit/v6"
 	"github.com/gofiber/fiber/v2"
 	"github.com/gojuno/minimock/v3"
 	"github.com/stretchr/testify/assert"
+
+	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/place/mocks"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
 )
 
-func Test_GetNestedPlacesHandler(t *testing.T) {
+func TestGetNestedPlacesHandler(t *testing.T) {
+	t.Parallel()
+
 	type req struct {
 		method string
 		route  string
 	}
 
 	var (
-		mc        = minimock.NewController(t)
 		placeID   = gofakeit.Number(1, 1000)
 		testError = errors.New(gofakeit.Phrase())
 		layout    = "2006-01-02 15:04:05"
@@ -66,15 +66,15 @@ func Test_GetNestedPlacesHandler(t *testing.T) {
 		req           req
 		resCode       int
 		resBody       interface{}
-		placeRepoMock func(mc *minimock.Controller) interfaces.PlaceRepository
+		placeRepoMock func(mc *minimock.Controller) PlaceRepository
 	}{
 		{
 			name:    "positive case",
 			req:     correctReq,
 			resCode: fiber.StatusOK,
 			resBody: expectedRes,
-			placeRepoMock: func(mc *minimock.Controller) interfaces.PlaceRepository {
-				mock := repoMocks.NewPlaceRepositoryMock(mc)
+			placeRepoMock: func(mc *minimock.Controller) PlaceRepository {
+				mock := mocks.NewPlaceRepositoryMock(mc)
 
 				mock.GetNestedPlacesMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, placeID, id)
@@ -87,8 +87,8 @@ func Test_GetNestedPlacesHandler(t *testing.T) {
 			name:    "negative case - repository error",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			placeRepoMock: func(mc *minimock.Controller) interfaces.PlaceRepository {
-				mock := repoMocks.NewPlaceRepositoryMock(mc)
+			placeRepoMock: func(mc *minimock.Controller) PlaceRepository {
+				mock := mocks.NewPlaceRepositoryMock(mc)
 
 				mock.GetNestedPlacesMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, placeID, id)
@@ -105,18 +105,19 @@ func Test_GetNestedPlacesHandler(t *testing.T) {
 			},
 			resCode: fiber.StatusBadRequest,
 			resBody: nil,
-			placeRepoMock: func(mc *minimock.Controller) interfaces.PlaceRepository {
-				return repoMocks.NewPlaceRepositoryMock(mc)
+			placeRepoMock: func(mc *minimock.Controller) PlaceRepository {
+				return mocks.NewPlaceRepositoryMock(mc)
 			},
 		},
 	}
 
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			fiberApp := fiber.New()
-			serviceProvider := sp.InitMock(tt.placeRepoMock(mc))
+			t.Parallel()
 
-			fiberApp.Get("/v1/places/:parentPlaceId/nested", GetNestedPlacesHandler(serviceProvider))
+			mc := minimock.NewController(t)
+			fiberApp := fiber.New()
+			fiberApp.Get("/v1/places/:parentPlaceId/nested", GetNestedPlacesHandler(tt.placeRepoMock(mc)))
 
 			fiberRes, _ := fiberApp.Test(httptest.NewRequest(tt.req.method, tt.req.route, nil), API.DefaultTestTimeOut)
 			assert.Equal(t, tt.resCode, fiberRes.StatusCode)

+ 22 - 21
internal/api/v1/place/get_place_test.go

@@ -8,27 +8,27 @@ import (
 	"strconv"
 	"testing"
 
-	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
-	repoMocks "git.dmitriygnatenko.ru/dima/homethings/internal/repositories/mocks"
-	sp "git.dmitriygnatenko.ru/dima/homethings/internal/service_provider"
 	"github.com/brianvoe/gofakeit/v6"
 	"github.com/gofiber/fiber/v2"
 	"github.com/gojuno/minimock/v3"
 	"github.com/stretchr/testify/assert"
+
+	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/place/mocks"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
 )
 
-func Test_GetPlaceHandler(t *testing.T) {
+func TestGetPlaceHandler(t *testing.T) {
+	t.Parallel()
+
 	type req struct {
 		method string
 		route  string
 	}
 
 	var (
-		mc        = minimock.NewController(t)
 		placeID   = gofakeit.Number(1, 1000)
 		parentID  = gofakeit.Number(1, 1000)
 		testError = errors.New(gofakeit.Phrase())
@@ -61,15 +61,15 @@ func Test_GetPlaceHandler(t *testing.T) {
 		req           req
 		resCode       int
 		resBody       interface{}
-		placeRepoMock func(mc *minimock.Controller) interfaces.PlaceRepository
+		placeRepoMock func(mc *minimock.Controller) PlaceRepository
 	}{
 		{
 			name:    "positive case",
 			req:     correctReq,
 			resCode: fiber.StatusOK,
 			resBody: expectedRes,
-			placeRepoMock: func(mc *minimock.Controller) interfaces.PlaceRepository {
-				mock := repoMocks.NewPlaceRepositoryMock(mc)
+			placeRepoMock: func(mc *minimock.Controller) PlaceRepository {
+				mock := mocks.NewPlaceRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, placeID, id)
@@ -82,8 +82,8 @@ func Test_GetPlaceHandler(t *testing.T) {
 			name:    "negative case - not found",
 			req:     correctReq,
 			resCode: fiber.StatusNotFound,
-			placeRepoMock: func(mc *minimock.Controller) interfaces.PlaceRepository {
-				mock := repoMocks.NewPlaceRepositoryMock(mc)
+			placeRepoMock: func(mc *minimock.Controller) PlaceRepository {
+				mock := mocks.NewPlaceRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, placeID, id)
@@ -96,8 +96,8 @@ func Test_GetPlaceHandler(t *testing.T) {
 			name:    "negative case - repository error",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			placeRepoMock: func(mc *minimock.Controller) interfaces.PlaceRepository {
-				mock := repoMocks.NewPlaceRepositoryMock(mc)
+			placeRepoMock: func(mc *minimock.Controller) PlaceRepository {
+				mock := mocks.NewPlaceRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, placeID, id)
@@ -114,18 +114,19 @@ func Test_GetPlaceHandler(t *testing.T) {
 			},
 			resCode: fiber.StatusBadRequest,
 			resBody: nil,
-			placeRepoMock: func(mc *minimock.Controller) interfaces.PlaceRepository {
-				return repoMocks.NewPlaceRepositoryMock(mc)
+			placeRepoMock: func(mc *minimock.Controller) PlaceRepository {
+				return mocks.NewPlaceRepositoryMock(mc)
 			},
 		},
 	}
 
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			fiberApp := fiber.New()
-			serviceProvider := sp.InitMock(tt.placeRepoMock(mc))
+			t.Parallel()
 
-			fiberApp.Get("/v1/places/:placeId", GetPlaceHandler(serviceProvider))
+			mc := minimock.NewController(t)
+			fiberApp := fiber.New()
+			fiberApp.Get("/v1/places/:placeId", GetPlaceHandler(tt.placeRepoMock(mc)))
 
 			fiberRes, _ := fiberApp.Test(httptest.NewRequest(tt.req.method, tt.req.route, nil), API.DefaultTestTimeOut)
 			assert.Equal(t, tt.resCode, fiberRes.StatusCode)

+ 5 - 5
internal/api/v1/place/get_place_tree.go

@@ -1,10 +1,10 @@
 package place
 
 import (
+	"github.com/gofiber/fiber/v2"
+
 	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/mappers"
-	"github.com/gofiber/fiber/v2"
 )
 
 // @Router 		/api/v1/places/tree [get]
@@ -15,15 +15,15 @@ import (
 // @security 	APIKey
 // @Accept      json
 // @Produce     json
-func GetPlaceTreeHandler(sp interfaces.ServiceProvider) fiber.Handler {
+func GetPlaceTreeHandler(placeRepository PlaceRepository) fiber.Handler {
 	return func(fctx *fiber.Ctx) error {
-		res, err := sp.GetPlaceRepository().GetAll(fctx.Context())
+		res, err := placeRepository.GetAll(fctx.Context())
 		if err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
 		res = helpers.ApplyLocation(fctx, res)
 
-		return fctx.JSON(mappers.ConvertToPlaceTreeResponseDTO(res))
+		return fctx.JSON(mappers.ToPlaceTreeResponse(res))
 	}
 }

+ 18 - 17
internal/api/v1/place/get_place_tree_test.go

@@ -6,27 +6,27 @@ import (
 	"net/http/httptest"
 	"testing"
 
-	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
-	repoMocks "git.dmitriygnatenko.ru/dima/homethings/internal/repositories/mocks"
-	sp "git.dmitriygnatenko.ru/dima/homethings/internal/service_provider"
 	"github.com/brianvoe/gofakeit/v6"
 	"github.com/gofiber/fiber/v2"
 	"github.com/gojuno/minimock/v3"
 	"github.com/stretchr/testify/assert"
+
+	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/place/mocks"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
 )
 
-func Test_GetPlaceTreeHandler(t *testing.T) {
+func TestGetPlaceTreeHandler(t *testing.T) {
+	t.Parallel()
+
 	type req struct {
 		method string
 		route  string
 	}
 
 	var (
-		mc        = minimock.NewController(t)
 		testError = errors.New(gofakeit.Phrase())
 		layout    = "2006-01-02 15:04:05"
 
@@ -104,15 +104,15 @@ func Test_GetPlaceTreeHandler(t *testing.T) {
 		req           req
 		resCode       int
 		resBody       interface{}
-		placeRepoMock func(mc *minimock.Controller) interfaces.PlaceRepository
+		placeRepoMock func(mc *minimock.Controller) PlaceRepository
 	}{
 		{
 			name:    "positive case",
 			req:     correctReq,
 			resCode: fiber.StatusOK,
 			resBody: expectedRes,
-			placeRepoMock: func(mc *minimock.Controller) interfaces.PlaceRepository {
-				mock := repoMocks.NewPlaceRepositoryMock(mc)
+			placeRepoMock: func(mc *minimock.Controller) PlaceRepository {
+				mock := mocks.NewPlaceRepositoryMock(mc)
 				mock.GetAllMock.Return(placeRepoRes, nil)
 				return mock
 			},
@@ -121,8 +121,8 @@ func Test_GetPlaceTreeHandler(t *testing.T) {
 			name:    "negative case - repository error",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			placeRepoMock: func(mc *minimock.Controller) interfaces.PlaceRepository {
-				mock := repoMocks.NewPlaceRepositoryMock(mc)
+			placeRepoMock: func(mc *minimock.Controller) PlaceRepository {
+				mock := mocks.NewPlaceRepositoryMock(mc)
 				mock.GetAllMock.Return(nil, testError)
 				return mock
 			},
@@ -131,10 +131,11 @@ func Test_GetPlaceTreeHandler(t *testing.T) {
 
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			fiberApp := fiber.New()
-			serviceProvider := sp.InitMock(tt.placeRepoMock(mc))
+			t.Parallel()
 
-			fiberApp.Get("/v1/places/tree", GetPlaceTreeHandler(serviceProvider))
+			mc := minimock.NewController(t)
+			fiberApp := fiber.New()
+			fiberApp.Get("/v1/places/tree", GetPlaceTreeHandler(tt.placeRepoMock(mc)))
 
 			fiberRes, _ := fiberApp.Test(httptest.NewRequest(tt.req.method, tt.req.route, nil), API.DefaultTestTimeOut)
 			assert.Equal(t, tt.resCode, fiberRes.StatusCode)

+ 5 - 5
internal/api/v1/place/get_places.go

@@ -1,10 +1,10 @@
 package place
 
 import (
+	"github.com/gofiber/fiber/v2"
+
 	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/mappers"
-	"github.com/gofiber/fiber/v2"
 )
 
 // @Router 		/api/v1/places [get]
@@ -15,15 +15,15 @@ import (
 // @security 	APIKey
 // @Accept      json
 // @Produce     json
-func GetPlacesHandler(sp interfaces.ServiceProvider) fiber.Handler {
+func GetPlacesHandler(placeRepository PlaceRepository) fiber.Handler {
 	return func(fctx *fiber.Ctx) error {
-		res, err := sp.GetPlaceRepository().GetAll(fctx.Context())
+		res, err := placeRepository.GetAll(fctx.Context())
 		if err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
 		res = helpers.ApplyLocation(fctx, res)
 
-		return fctx.JSON(mappers.ConvertToPlacesResponseDTO(res))
+		return fctx.JSON(mappers.ToPlacesResponse(res))
 	}
 }

+ 18 - 17
internal/api/v1/place/get_places_test.go

@@ -6,27 +6,27 @@ import (
 	"net/http/httptest"
 	"testing"
 
-	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
-	repoMocks "git.dmitriygnatenko.ru/dima/homethings/internal/repositories/mocks"
-	sp "git.dmitriygnatenko.ru/dima/homethings/internal/service_provider"
 	"github.com/brianvoe/gofakeit/v6"
 	"github.com/gofiber/fiber/v2"
 	"github.com/gojuno/minimock/v3"
 	"github.com/stretchr/testify/assert"
+
+	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/place/mocks"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
 )
 
-func Test_GetPlacesHandler(t *testing.T) {
+func TestGetPlacesHandler(t *testing.T) {
+	t.Parallel()
+
 	type req struct {
 		method string
 		route  string
 	}
 
 	var (
-		mc        = minimock.NewController(t)
 		testError = errors.New(gofakeit.Phrase())
 		layout    = "2006-01-02 15:04:05"
 
@@ -94,15 +94,15 @@ func Test_GetPlacesHandler(t *testing.T) {
 		req           req
 		resCode       int
 		resBody       interface{}
-		placeRepoMock func(mc *minimock.Controller) interfaces.PlaceRepository
+		placeRepoMock func(mc *minimock.Controller) PlaceRepository
 	}{
 		{
 			name:    "positive case",
 			req:     correctReq,
 			resCode: fiber.StatusOK,
 			resBody: expectedRes,
-			placeRepoMock: func(mc *minimock.Controller) interfaces.PlaceRepository {
-				mock := repoMocks.NewPlaceRepositoryMock(mc)
+			placeRepoMock: func(mc *minimock.Controller) PlaceRepository {
+				mock := mocks.NewPlaceRepositoryMock(mc)
 				mock.GetAllMock.Return(placeRepoRes, nil)
 				return mock
 			},
@@ -111,8 +111,8 @@ func Test_GetPlacesHandler(t *testing.T) {
 			name:    "negative case - repository error",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			placeRepoMock: func(mc *minimock.Controller) interfaces.PlaceRepository {
-				mock := repoMocks.NewPlaceRepositoryMock(mc)
+			placeRepoMock: func(mc *minimock.Controller) PlaceRepository {
+				mock := mocks.NewPlaceRepositoryMock(mc)
 				mock.GetAllMock.Return(nil, testError)
 				return mock
 			},
@@ -121,10 +121,11 @@ func Test_GetPlacesHandler(t *testing.T) {
 
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			fiberApp := fiber.New()
-			serviceProvider := sp.InitMock(tt.placeRepoMock(mc))
+			t.Parallel()
 
-			fiberApp.Get("/v1/places", GetPlacesHandler(serviceProvider))
+			mc := minimock.NewController(t)
+			fiberApp := fiber.New()
+			fiberApp.Get("/v1/places", GetPlacesHandler(tt.placeRepoMock(mc)))
 
 			fiberRes, _ := fiberApp.Test(httptest.NewRequest(tt.req.method, tt.req.route, nil), API.DefaultTestTimeOut)
 			assert.Equal(t, tt.resCode, fiberRes.StatusCode)

+ 364 - 0
internal/api/v1/place/mocks/file_repository_minimock.go

@@ -0,0 +1,364 @@
+// Code generated by http://github.com/gojuno/minimock (v3.3.13). DO NOT EDIT.
+
+package mocks
+
+//go:generate minimock -i git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/place.FileRepository -o file_repository_minimock.go -n FileRepositoryMock -p mocks
+
+import (
+	"sync"
+	mm_atomic "sync/atomic"
+	mm_time "time"
+
+	"github.com/gojuno/minimock/v3"
+)
+
+// FileRepositoryMock implements place.FileRepository
+type FileRepositoryMock struct {
+	t          minimock.Tester
+	finishOnce sync.Once
+
+	funcDelete          func(path string) (err error)
+	inspectFuncDelete   func(path string)
+	afterDeleteCounter  uint64
+	beforeDeleteCounter uint64
+	DeleteMock          mFileRepositoryMockDelete
+}
+
+// NewFileRepositoryMock returns a mock for place.FileRepository
+func NewFileRepositoryMock(t minimock.Tester) *FileRepositoryMock {
+	m := &FileRepositoryMock{t: t}
+
+	if controller, ok := t.(minimock.MockController); ok {
+		controller.RegisterMocker(m)
+	}
+
+	m.DeleteMock = mFileRepositoryMockDelete{mock: m}
+	m.DeleteMock.callArgs = []*FileRepositoryMockDeleteParams{}
+
+	t.Cleanup(m.MinimockFinish)
+
+	return m
+}
+
+type mFileRepositoryMockDelete struct {
+	optional           bool
+	mock               *FileRepositoryMock
+	defaultExpectation *FileRepositoryMockDeleteExpectation
+	expectations       []*FileRepositoryMockDeleteExpectation
+
+	callArgs []*FileRepositoryMockDeleteParams
+	mutex    sync.RWMutex
+
+	expectedInvocations uint64
+}
+
+// FileRepositoryMockDeleteExpectation specifies expectation struct of the FileRepository.Delete
+type FileRepositoryMockDeleteExpectation struct {
+	mock      *FileRepositoryMock
+	params    *FileRepositoryMockDeleteParams
+	paramPtrs *FileRepositoryMockDeleteParamPtrs
+	results   *FileRepositoryMockDeleteResults
+	Counter   uint64
+}
+
+// FileRepositoryMockDeleteParams contains parameters of the FileRepository.Delete
+type FileRepositoryMockDeleteParams struct {
+	path string
+}
+
+// FileRepositoryMockDeleteParamPtrs contains pointers to parameters of the FileRepository.Delete
+type FileRepositoryMockDeleteParamPtrs struct {
+	path *string
+}
+
+// FileRepositoryMockDeleteResults contains results of the FileRepository.Delete
+type FileRepositoryMockDeleteResults struct {
+	err error
+}
+
+// Marks this method to be optional. The default behavior of any method with Return() is '1 or more', meaning
+// the test will fail minimock's automatic final call check if the mocked method was not called at least once.
+// Optional() makes method check to work in '0 or more' mode.
+// It is NOT RECOMMENDED to use this option unless you really need it, as default behaviour helps to
+// catch the problems when the expected method call is totally skipped during test run.
+func (mmDelete *mFileRepositoryMockDelete) Optional() *mFileRepositoryMockDelete {
+	mmDelete.optional = true
+	return mmDelete
+}
+
+// Expect sets up expected params for FileRepository.Delete
+func (mmDelete *mFileRepositoryMockDelete) Expect(path string) *mFileRepositoryMockDelete {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("FileRepositoryMock.Delete mock is already set by Set")
+	}
+
+	if mmDelete.defaultExpectation == nil {
+		mmDelete.defaultExpectation = &FileRepositoryMockDeleteExpectation{}
+	}
+
+	if mmDelete.defaultExpectation.paramPtrs != nil {
+		mmDelete.mock.t.Fatalf("FileRepositoryMock.Delete mock is already set by ExpectParams functions")
+	}
+
+	mmDelete.defaultExpectation.params = &FileRepositoryMockDeleteParams{path}
+	for _, e := range mmDelete.expectations {
+		if minimock.Equal(e.params, mmDelete.defaultExpectation.params) {
+			mmDelete.mock.t.Fatalf("Expectation set by When has same params: %#v", *mmDelete.defaultExpectation.params)
+		}
+	}
+
+	return mmDelete
+}
+
+// ExpectPathParam1 sets up expected param path for FileRepository.Delete
+func (mmDelete *mFileRepositoryMockDelete) ExpectPathParam1(path string) *mFileRepositoryMockDelete {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("FileRepositoryMock.Delete mock is already set by Set")
+	}
+
+	if mmDelete.defaultExpectation == nil {
+		mmDelete.defaultExpectation = &FileRepositoryMockDeleteExpectation{}
+	}
+
+	if mmDelete.defaultExpectation.params != nil {
+		mmDelete.mock.t.Fatalf("FileRepositoryMock.Delete mock is already set by Expect")
+	}
+
+	if mmDelete.defaultExpectation.paramPtrs == nil {
+		mmDelete.defaultExpectation.paramPtrs = &FileRepositoryMockDeleteParamPtrs{}
+	}
+	mmDelete.defaultExpectation.paramPtrs.path = &path
+
+	return mmDelete
+}
+
+// Inspect accepts an inspector function that has same arguments as the FileRepository.Delete
+func (mmDelete *mFileRepositoryMockDelete) Inspect(f func(path string)) *mFileRepositoryMockDelete {
+	if mmDelete.mock.inspectFuncDelete != nil {
+		mmDelete.mock.t.Fatalf("Inspect function is already set for FileRepositoryMock.Delete")
+	}
+
+	mmDelete.mock.inspectFuncDelete = f
+
+	return mmDelete
+}
+
+// Return sets up results that will be returned by FileRepository.Delete
+func (mmDelete *mFileRepositoryMockDelete) Return(err error) *FileRepositoryMock {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("FileRepositoryMock.Delete mock is already set by Set")
+	}
+
+	if mmDelete.defaultExpectation == nil {
+		mmDelete.defaultExpectation = &FileRepositoryMockDeleteExpectation{mock: mmDelete.mock}
+	}
+	mmDelete.defaultExpectation.results = &FileRepositoryMockDeleteResults{err}
+	return mmDelete.mock
+}
+
+// Set uses given function f to mock the FileRepository.Delete method
+func (mmDelete *mFileRepositoryMockDelete) Set(f func(path string) (err error)) *FileRepositoryMock {
+	if mmDelete.defaultExpectation != nil {
+		mmDelete.mock.t.Fatalf("Default expectation is already set for the FileRepository.Delete method")
+	}
+
+	if len(mmDelete.expectations) > 0 {
+		mmDelete.mock.t.Fatalf("Some expectations are already set for the FileRepository.Delete method")
+	}
+
+	mmDelete.mock.funcDelete = f
+	return mmDelete.mock
+}
+
+// When sets expectation for the FileRepository.Delete which will trigger the result defined by the following
+// Then helper
+func (mmDelete *mFileRepositoryMockDelete) When(path string) *FileRepositoryMockDeleteExpectation {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("FileRepositoryMock.Delete mock is already set by Set")
+	}
+
+	expectation := &FileRepositoryMockDeleteExpectation{
+		mock:   mmDelete.mock,
+		params: &FileRepositoryMockDeleteParams{path},
+	}
+	mmDelete.expectations = append(mmDelete.expectations, expectation)
+	return expectation
+}
+
+// Then sets up FileRepository.Delete return parameters for the expectation previously defined by the When method
+func (e *FileRepositoryMockDeleteExpectation) Then(err error) *FileRepositoryMock {
+	e.results = &FileRepositoryMockDeleteResults{err}
+	return e.mock
+}
+
+// Times sets number of times FileRepository.Delete should be invoked
+func (mmDelete *mFileRepositoryMockDelete) Times(n uint64) *mFileRepositoryMockDelete {
+	if n == 0 {
+		mmDelete.mock.t.Fatalf("Times of FileRepositoryMock.Delete mock can not be zero")
+	}
+	mm_atomic.StoreUint64(&mmDelete.expectedInvocations, n)
+	return mmDelete
+}
+
+func (mmDelete *mFileRepositoryMockDelete) invocationsDone() bool {
+	if len(mmDelete.expectations) == 0 && mmDelete.defaultExpectation == nil && mmDelete.mock.funcDelete == nil {
+		return true
+	}
+
+	totalInvocations := mm_atomic.LoadUint64(&mmDelete.mock.afterDeleteCounter)
+	expectedInvocations := mm_atomic.LoadUint64(&mmDelete.expectedInvocations)
+
+	return totalInvocations > 0 && (expectedInvocations == 0 || expectedInvocations == totalInvocations)
+}
+
+// Delete implements place.FileRepository
+func (mmDelete *FileRepositoryMock) Delete(path string) (err error) {
+	mm_atomic.AddUint64(&mmDelete.beforeDeleteCounter, 1)
+	defer mm_atomic.AddUint64(&mmDelete.afterDeleteCounter, 1)
+
+	if mmDelete.inspectFuncDelete != nil {
+		mmDelete.inspectFuncDelete(path)
+	}
+
+	mm_params := FileRepositoryMockDeleteParams{path}
+
+	// Record call args
+	mmDelete.DeleteMock.mutex.Lock()
+	mmDelete.DeleteMock.callArgs = append(mmDelete.DeleteMock.callArgs, &mm_params)
+	mmDelete.DeleteMock.mutex.Unlock()
+
+	for _, e := range mmDelete.DeleteMock.expectations {
+		if minimock.Equal(*e.params, mm_params) {
+			mm_atomic.AddUint64(&e.Counter, 1)
+			return e.results.err
+		}
+	}
+
+	if mmDelete.DeleteMock.defaultExpectation != nil {
+		mm_atomic.AddUint64(&mmDelete.DeleteMock.defaultExpectation.Counter, 1)
+		mm_want := mmDelete.DeleteMock.defaultExpectation.params
+		mm_want_ptrs := mmDelete.DeleteMock.defaultExpectation.paramPtrs
+
+		mm_got := FileRepositoryMockDeleteParams{path}
+
+		if mm_want_ptrs != nil {
+
+			if mm_want_ptrs.path != nil && !minimock.Equal(*mm_want_ptrs.path, mm_got.path) {
+				mmDelete.t.Errorf("FileRepositoryMock.Delete got unexpected parameter path, want: %#v, got: %#v%s\n", *mm_want_ptrs.path, mm_got.path, minimock.Diff(*mm_want_ptrs.path, mm_got.path))
+			}
+
+		} else if mm_want != nil && !minimock.Equal(*mm_want, mm_got) {
+			mmDelete.t.Errorf("FileRepositoryMock.Delete got unexpected parameters, want: %#v, got: %#v%s\n", *mm_want, mm_got, minimock.Diff(*mm_want, mm_got))
+		}
+
+		mm_results := mmDelete.DeleteMock.defaultExpectation.results
+		if mm_results == nil {
+			mmDelete.t.Fatal("No results are set for the FileRepositoryMock.Delete")
+		}
+		return (*mm_results).err
+	}
+	if mmDelete.funcDelete != nil {
+		return mmDelete.funcDelete(path)
+	}
+	mmDelete.t.Fatalf("Unexpected call to FileRepositoryMock.Delete. %v", path)
+	return
+}
+
+// DeleteAfterCounter returns a count of finished FileRepositoryMock.Delete invocations
+func (mmDelete *FileRepositoryMock) DeleteAfterCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmDelete.afterDeleteCounter)
+}
+
+// DeleteBeforeCounter returns a count of FileRepositoryMock.Delete invocations
+func (mmDelete *FileRepositoryMock) DeleteBeforeCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmDelete.beforeDeleteCounter)
+}
+
+// Calls returns a list of arguments used in each call to FileRepositoryMock.Delete.
+// The list is in the same order as the calls were made (i.e. recent calls have a higher index)
+func (mmDelete *mFileRepositoryMockDelete) Calls() []*FileRepositoryMockDeleteParams {
+	mmDelete.mutex.RLock()
+
+	argCopy := make([]*FileRepositoryMockDeleteParams, len(mmDelete.callArgs))
+	copy(argCopy, mmDelete.callArgs)
+
+	mmDelete.mutex.RUnlock()
+
+	return argCopy
+}
+
+// MinimockDeleteDone returns true if the count of the Delete invocations corresponds
+// the number of defined expectations
+func (m *FileRepositoryMock) MinimockDeleteDone() bool {
+	if m.DeleteMock.optional {
+		// Optional methods provide '0 or more' call count restriction.
+		return true
+	}
+
+	for _, e := range m.DeleteMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			return false
+		}
+	}
+
+	return m.DeleteMock.invocationsDone()
+}
+
+// MinimockDeleteInspect logs each unmet expectation
+func (m *FileRepositoryMock) MinimockDeleteInspect() {
+	for _, e := range m.DeleteMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			m.t.Errorf("Expected call to FileRepositoryMock.Delete with params: %#v", *e.params)
+		}
+	}
+
+	afterDeleteCounter := mm_atomic.LoadUint64(&m.afterDeleteCounter)
+	// if default expectation was set then invocations count should be greater than zero
+	if m.DeleteMock.defaultExpectation != nil && afterDeleteCounter < 1 {
+		if m.DeleteMock.defaultExpectation.params == nil {
+			m.t.Error("Expected call to FileRepositoryMock.Delete")
+		} else {
+			m.t.Errorf("Expected call to FileRepositoryMock.Delete with params: %#v", *m.DeleteMock.defaultExpectation.params)
+		}
+	}
+	// if func was set then invocations count should be greater than zero
+	if m.funcDelete != nil && afterDeleteCounter < 1 {
+		m.t.Error("Expected call to FileRepositoryMock.Delete")
+	}
+
+	if !m.DeleteMock.invocationsDone() && afterDeleteCounter > 0 {
+		m.t.Errorf("Expected %d calls to FileRepositoryMock.Delete but found %d calls",
+			mm_atomic.LoadUint64(&m.DeleteMock.expectedInvocations), afterDeleteCounter)
+	}
+}
+
+// MinimockFinish checks that all mocked methods have been called the expected number of times
+func (m *FileRepositoryMock) MinimockFinish() {
+	m.finishOnce.Do(func() {
+		if !m.minimockDone() {
+			m.MinimockDeleteInspect()
+		}
+	})
+}
+
+// MinimockWait waits for all mocked methods to be called the expected number of times
+func (m *FileRepositoryMock) MinimockWait(timeout mm_time.Duration) {
+	timeoutCh := mm_time.After(timeout)
+	for {
+		if m.minimockDone() {
+			return
+		}
+		select {
+		case <-timeoutCh:
+			m.MinimockFinish()
+			return
+		case <-mm_time.After(10 * mm_time.Millisecond):
+		}
+	}
+}
+
+func (m *FileRepositoryMock) minimockDone() bool {
+	done := true
+	return done &&
+		m.MinimockDeleteDone()
+}

+ 756 - 0
internal/api/v1/place/mocks/place_image_repository_minimock.go

@@ -0,0 +1,756 @@
+// Code generated by http://github.com/gojuno/minimock (v3.3.13). DO NOT EDIT.
+
+package mocks
+
+//go:generate minimock -i git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/place.PlaceImageRepository -o place_image_repository_minimock.go -n PlaceImageRepositoryMock -p mocks
+
+import (
+	"context"
+	"database/sql"
+	"sync"
+	mm_atomic "sync/atomic"
+	mm_time "time"
+
+	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
+	"github.com/gojuno/minimock/v3"
+)
+
+// PlaceImageRepositoryMock implements place.PlaceImageRepository
+type PlaceImageRepositoryMock struct {
+	t          minimock.Tester
+	finishOnce sync.Once
+
+	funcDelete          func(ctx context.Context, imageID int, tx *sql.Tx) (err error)
+	inspectFuncDelete   func(ctx context.Context, imageID int, tx *sql.Tx)
+	afterDeleteCounter  uint64
+	beforeDeleteCounter uint64
+	DeleteMock          mPlaceImageRepositoryMockDelete
+
+	funcGetByPlaceID          func(ctx context.Context, placeID int) (ia1 []models.Image, err error)
+	inspectFuncGetByPlaceID   func(ctx context.Context, placeID int)
+	afterGetByPlaceIDCounter  uint64
+	beforeGetByPlaceIDCounter uint64
+	GetByPlaceIDMock          mPlaceImageRepositoryMockGetByPlaceID
+}
+
+// NewPlaceImageRepositoryMock returns a mock for place.PlaceImageRepository
+func NewPlaceImageRepositoryMock(t minimock.Tester) *PlaceImageRepositoryMock {
+	m := &PlaceImageRepositoryMock{t: t}
+
+	if controller, ok := t.(minimock.MockController); ok {
+		controller.RegisterMocker(m)
+	}
+
+	m.DeleteMock = mPlaceImageRepositoryMockDelete{mock: m}
+	m.DeleteMock.callArgs = []*PlaceImageRepositoryMockDeleteParams{}
+
+	m.GetByPlaceIDMock = mPlaceImageRepositoryMockGetByPlaceID{mock: m}
+	m.GetByPlaceIDMock.callArgs = []*PlaceImageRepositoryMockGetByPlaceIDParams{}
+
+	t.Cleanup(m.MinimockFinish)
+
+	return m
+}
+
+type mPlaceImageRepositoryMockDelete struct {
+	optional           bool
+	mock               *PlaceImageRepositoryMock
+	defaultExpectation *PlaceImageRepositoryMockDeleteExpectation
+	expectations       []*PlaceImageRepositoryMockDeleteExpectation
+
+	callArgs []*PlaceImageRepositoryMockDeleteParams
+	mutex    sync.RWMutex
+
+	expectedInvocations uint64
+}
+
+// PlaceImageRepositoryMockDeleteExpectation specifies expectation struct of the PlaceImageRepository.Delete
+type PlaceImageRepositoryMockDeleteExpectation struct {
+	mock      *PlaceImageRepositoryMock
+	params    *PlaceImageRepositoryMockDeleteParams
+	paramPtrs *PlaceImageRepositoryMockDeleteParamPtrs
+	results   *PlaceImageRepositoryMockDeleteResults
+	Counter   uint64
+}
+
+// PlaceImageRepositoryMockDeleteParams contains parameters of the PlaceImageRepository.Delete
+type PlaceImageRepositoryMockDeleteParams struct {
+	ctx     context.Context
+	imageID int
+	tx      *sql.Tx
+}
+
+// PlaceImageRepositoryMockDeleteParamPtrs contains pointers to parameters of the PlaceImageRepository.Delete
+type PlaceImageRepositoryMockDeleteParamPtrs struct {
+	ctx     *context.Context
+	imageID *int
+	tx      **sql.Tx
+}
+
+// PlaceImageRepositoryMockDeleteResults contains results of the PlaceImageRepository.Delete
+type PlaceImageRepositoryMockDeleteResults struct {
+	err error
+}
+
+// Marks this method to be optional. The default behavior of any method with Return() is '1 or more', meaning
+// the test will fail minimock's automatic final call check if the mocked method was not called at least once.
+// Optional() makes method check to work in '0 or more' mode.
+// It is NOT RECOMMENDED to use this option unless you really need it, as default behaviour helps to
+// catch the problems when the expected method call is totally skipped during test run.
+func (mmDelete *mPlaceImageRepositoryMockDelete) Optional() *mPlaceImageRepositoryMockDelete {
+	mmDelete.optional = true
+	return mmDelete
+}
+
+// Expect sets up expected params for PlaceImageRepository.Delete
+func (mmDelete *mPlaceImageRepositoryMockDelete) Expect(ctx context.Context, imageID int, tx *sql.Tx) *mPlaceImageRepositoryMockDelete {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("PlaceImageRepositoryMock.Delete mock is already set by Set")
+	}
+
+	if mmDelete.defaultExpectation == nil {
+		mmDelete.defaultExpectation = &PlaceImageRepositoryMockDeleteExpectation{}
+	}
+
+	if mmDelete.defaultExpectation.paramPtrs != nil {
+		mmDelete.mock.t.Fatalf("PlaceImageRepositoryMock.Delete mock is already set by ExpectParams functions")
+	}
+
+	mmDelete.defaultExpectation.params = &PlaceImageRepositoryMockDeleteParams{ctx, imageID, tx}
+	for _, e := range mmDelete.expectations {
+		if minimock.Equal(e.params, mmDelete.defaultExpectation.params) {
+			mmDelete.mock.t.Fatalf("Expectation set by When has same params: %#v", *mmDelete.defaultExpectation.params)
+		}
+	}
+
+	return mmDelete
+}
+
+// ExpectCtxParam1 sets up expected param ctx for PlaceImageRepository.Delete
+func (mmDelete *mPlaceImageRepositoryMockDelete) ExpectCtxParam1(ctx context.Context) *mPlaceImageRepositoryMockDelete {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("PlaceImageRepositoryMock.Delete mock is already set by Set")
+	}
+
+	if mmDelete.defaultExpectation == nil {
+		mmDelete.defaultExpectation = &PlaceImageRepositoryMockDeleteExpectation{}
+	}
+
+	if mmDelete.defaultExpectation.params != nil {
+		mmDelete.mock.t.Fatalf("PlaceImageRepositoryMock.Delete mock is already set by Expect")
+	}
+
+	if mmDelete.defaultExpectation.paramPtrs == nil {
+		mmDelete.defaultExpectation.paramPtrs = &PlaceImageRepositoryMockDeleteParamPtrs{}
+	}
+	mmDelete.defaultExpectation.paramPtrs.ctx = &ctx
+
+	return mmDelete
+}
+
+// ExpectImageIDParam2 sets up expected param imageID for PlaceImageRepository.Delete
+func (mmDelete *mPlaceImageRepositoryMockDelete) ExpectImageIDParam2(imageID int) *mPlaceImageRepositoryMockDelete {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("PlaceImageRepositoryMock.Delete mock is already set by Set")
+	}
+
+	if mmDelete.defaultExpectation == nil {
+		mmDelete.defaultExpectation = &PlaceImageRepositoryMockDeleteExpectation{}
+	}
+
+	if mmDelete.defaultExpectation.params != nil {
+		mmDelete.mock.t.Fatalf("PlaceImageRepositoryMock.Delete mock is already set by Expect")
+	}
+
+	if mmDelete.defaultExpectation.paramPtrs == nil {
+		mmDelete.defaultExpectation.paramPtrs = &PlaceImageRepositoryMockDeleteParamPtrs{}
+	}
+	mmDelete.defaultExpectation.paramPtrs.imageID = &imageID
+
+	return mmDelete
+}
+
+// ExpectTxParam3 sets up expected param tx for PlaceImageRepository.Delete
+func (mmDelete *mPlaceImageRepositoryMockDelete) ExpectTxParam3(tx *sql.Tx) *mPlaceImageRepositoryMockDelete {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("PlaceImageRepositoryMock.Delete mock is already set by Set")
+	}
+
+	if mmDelete.defaultExpectation == nil {
+		mmDelete.defaultExpectation = &PlaceImageRepositoryMockDeleteExpectation{}
+	}
+
+	if mmDelete.defaultExpectation.params != nil {
+		mmDelete.mock.t.Fatalf("PlaceImageRepositoryMock.Delete mock is already set by Expect")
+	}
+
+	if mmDelete.defaultExpectation.paramPtrs == nil {
+		mmDelete.defaultExpectation.paramPtrs = &PlaceImageRepositoryMockDeleteParamPtrs{}
+	}
+	mmDelete.defaultExpectation.paramPtrs.tx = &tx
+
+	return mmDelete
+}
+
+// Inspect accepts an inspector function that has same arguments as the PlaceImageRepository.Delete
+func (mmDelete *mPlaceImageRepositoryMockDelete) Inspect(f func(ctx context.Context, imageID int, tx *sql.Tx)) *mPlaceImageRepositoryMockDelete {
+	if mmDelete.mock.inspectFuncDelete != nil {
+		mmDelete.mock.t.Fatalf("Inspect function is already set for PlaceImageRepositoryMock.Delete")
+	}
+
+	mmDelete.mock.inspectFuncDelete = f
+
+	return mmDelete
+}
+
+// Return sets up results that will be returned by PlaceImageRepository.Delete
+func (mmDelete *mPlaceImageRepositoryMockDelete) Return(err error) *PlaceImageRepositoryMock {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("PlaceImageRepositoryMock.Delete mock is already set by Set")
+	}
+
+	if mmDelete.defaultExpectation == nil {
+		mmDelete.defaultExpectation = &PlaceImageRepositoryMockDeleteExpectation{mock: mmDelete.mock}
+	}
+	mmDelete.defaultExpectation.results = &PlaceImageRepositoryMockDeleteResults{err}
+	return mmDelete.mock
+}
+
+// Set uses given function f to mock the PlaceImageRepository.Delete method
+func (mmDelete *mPlaceImageRepositoryMockDelete) Set(f func(ctx context.Context, imageID int, tx *sql.Tx) (err error)) *PlaceImageRepositoryMock {
+	if mmDelete.defaultExpectation != nil {
+		mmDelete.mock.t.Fatalf("Default expectation is already set for the PlaceImageRepository.Delete method")
+	}
+
+	if len(mmDelete.expectations) > 0 {
+		mmDelete.mock.t.Fatalf("Some expectations are already set for the PlaceImageRepository.Delete method")
+	}
+
+	mmDelete.mock.funcDelete = f
+	return mmDelete.mock
+}
+
+// When sets expectation for the PlaceImageRepository.Delete which will trigger the result defined by the following
+// Then helper
+func (mmDelete *mPlaceImageRepositoryMockDelete) When(ctx context.Context, imageID int, tx *sql.Tx) *PlaceImageRepositoryMockDeleteExpectation {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("PlaceImageRepositoryMock.Delete mock is already set by Set")
+	}
+
+	expectation := &PlaceImageRepositoryMockDeleteExpectation{
+		mock:   mmDelete.mock,
+		params: &PlaceImageRepositoryMockDeleteParams{ctx, imageID, tx},
+	}
+	mmDelete.expectations = append(mmDelete.expectations, expectation)
+	return expectation
+}
+
+// Then sets up PlaceImageRepository.Delete return parameters for the expectation previously defined by the When method
+func (e *PlaceImageRepositoryMockDeleteExpectation) Then(err error) *PlaceImageRepositoryMock {
+	e.results = &PlaceImageRepositoryMockDeleteResults{err}
+	return e.mock
+}
+
+// Times sets number of times PlaceImageRepository.Delete should be invoked
+func (mmDelete *mPlaceImageRepositoryMockDelete) Times(n uint64) *mPlaceImageRepositoryMockDelete {
+	if n == 0 {
+		mmDelete.mock.t.Fatalf("Times of PlaceImageRepositoryMock.Delete mock can not be zero")
+	}
+	mm_atomic.StoreUint64(&mmDelete.expectedInvocations, n)
+	return mmDelete
+}
+
+func (mmDelete *mPlaceImageRepositoryMockDelete) invocationsDone() bool {
+	if len(mmDelete.expectations) == 0 && mmDelete.defaultExpectation == nil && mmDelete.mock.funcDelete == nil {
+		return true
+	}
+
+	totalInvocations := mm_atomic.LoadUint64(&mmDelete.mock.afterDeleteCounter)
+	expectedInvocations := mm_atomic.LoadUint64(&mmDelete.expectedInvocations)
+
+	return totalInvocations > 0 && (expectedInvocations == 0 || expectedInvocations == totalInvocations)
+}
+
+// Delete implements place.PlaceImageRepository
+func (mmDelete *PlaceImageRepositoryMock) Delete(ctx context.Context, imageID int, tx *sql.Tx) (err error) {
+	mm_atomic.AddUint64(&mmDelete.beforeDeleteCounter, 1)
+	defer mm_atomic.AddUint64(&mmDelete.afterDeleteCounter, 1)
+
+	if mmDelete.inspectFuncDelete != nil {
+		mmDelete.inspectFuncDelete(ctx, imageID, tx)
+	}
+
+	mm_params := PlaceImageRepositoryMockDeleteParams{ctx, imageID, tx}
+
+	// Record call args
+	mmDelete.DeleteMock.mutex.Lock()
+	mmDelete.DeleteMock.callArgs = append(mmDelete.DeleteMock.callArgs, &mm_params)
+	mmDelete.DeleteMock.mutex.Unlock()
+
+	for _, e := range mmDelete.DeleteMock.expectations {
+		if minimock.Equal(*e.params, mm_params) {
+			mm_atomic.AddUint64(&e.Counter, 1)
+			return e.results.err
+		}
+	}
+
+	if mmDelete.DeleteMock.defaultExpectation != nil {
+		mm_atomic.AddUint64(&mmDelete.DeleteMock.defaultExpectation.Counter, 1)
+		mm_want := mmDelete.DeleteMock.defaultExpectation.params
+		mm_want_ptrs := mmDelete.DeleteMock.defaultExpectation.paramPtrs
+
+		mm_got := PlaceImageRepositoryMockDeleteParams{ctx, imageID, tx}
+
+		if mm_want_ptrs != nil {
+
+			if mm_want_ptrs.ctx != nil && !minimock.Equal(*mm_want_ptrs.ctx, mm_got.ctx) {
+				mmDelete.t.Errorf("PlaceImageRepositoryMock.Delete got unexpected parameter ctx, want: %#v, got: %#v%s\n", *mm_want_ptrs.ctx, mm_got.ctx, minimock.Diff(*mm_want_ptrs.ctx, mm_got.ctx))
+			}
+
+			if mm_want_ptrs.imageID != nil && !minimock.Equal(*mm_want_ptrs.imageID, mm_got.imageID) {
+				mmDelete.t.Errorf("PlaceImageRepositoryMock.Delete got unexpected parameter imageID, want: %#v, got: %#v%s\n", *mm_want_ptrs.imageID, mm_got.imageID, minimock.Diff(*mm_want_ptrs.imageID, mm_got.imageID))
+			}
+
+			if mm_want_ptrs.tx != nil && !minimock.Equal(*mm_want_ptrs.tx, mm_got.tx) {
+				mmDelete.t.Errorf("PlaceImageRepositoryMock.Delete got unexpected parameter tx, want: %#v, got: %#v%s\n", *mm_want_ptrs.tx, mm_got.tx, minimock.Diff(*mm_want_ptrs.tx, mm_got.tx))
+			}
+
+		} else if mm_want != nil && !minimock.Equal(*mm_want, mm_got) {
+			mmDelete.t.Errorf("PlaceImageRepositoryMock.Delete got unexpected parameters, want: %#v, got: %#v%s\n", *mm_want, mm_got, minimock.Diff(*mm_want, mm_got))
+		}
+
+		mm_results := mmDelete.DeleteMock.defaultExpectation.results
+		if mm_results == nil {
+			mmDelete.t.Fatal("No results are set for the PlaceImageRepositoryMock.Delete")
+		}
+		return (*mm_results).err
+	}
+	if mmDelete.funcDelete != nil {
+		return mmDelete.funcDelete(ctx, imageID, tx)
+	}
+	mmDelete.t.Fatalf("Unexpected call to PlaceImageRepositoryMock.Delete. %v %v %v", ctx, imageID, tx)
+	return
+}
+
+// DeleteAfterCounter returns a count of finished PlaceImageRepositoryMock.Delete invocations
+func (mmDelete *PlaceImageRepositoryMock) DeleteAfterCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmDelete.afterDeleteCounter)
+}
+
+// DeleteBeforeCounter returns a count of PlaceImageRepositoryMock.Delete invocations
+func (mmDelete *PlaceImageRepositoryMock) DeleteBeforeCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmDelete.beforeDeleteCounter)
+}
+
+// Calls returns a list of arguments used in each call to PlaceImageRepositoryMock.Delete.
+// The list is in the same order as the calls were made (i.e. recent calls have a higher index)
+func (mmDelete *mPlaceImageRepositoryMockDelete) Calls() []*PlaceImageRepositoryMockDeleteParams {
+	mmDelete.mutex.RLock()
+
+	argCopy := make([]*PlaceImageRepositoryMockDeleteParams, len(mmDelete.callArgs))
+	copy(argCopy, mmDelete.callArgs)
+
+	mmDelete.mutex.RUnlock()
+
+	return argCopy
+}
+
+// MinimockDeleteDone returns true if the count of the Delete invocations corresponds
+// the number of defined expectations
+func (m *PlaceImageRepositoryMock) MinimockDeleteDone() bool {
+	if m.DeleteMock.optional {
+		// Optional methods provide '0 or more' call count restriction.
+		return true
+	}
+
+	for _, e := range m.DeleteMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			return false
+		}
+	}
+
+	return m.DeleteMock.invocationsDone()
+}
+
+// MinimockDeleteInspect logs each unmet expectation
+func (m *PlaceImageRepositoryMock) MinimockDeleteInspect() {
+	for _, e := range m.DeleteMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			m.t.Errorf("Expected call to PlaceImageRepositoryMock.Delete with params: %#v", *e.params)
+		}
+	}
+
+	afterDeleteCounter := mm_atomic.LoadUint64(&m.afterDeleteCounter)
+	// if default expectation was set then invocations count should be greater than zero
+	if m.DeleteMock.defaultExpectation != nil && afterDeleteCounter < 1 {
+		if m.DeleteMock.defaultExpectation.params == nil {
+			m.t.Error("Expected call to PlaceImageRepositoryMock.Delete")
+		} else {
+			m.t.Errorf("Expected call to PlaceImageRepositoryMock.Delete with params: %#v", *m.DeleteMock.defaultExpectation.params)
+		}
+	}
+	// if func was set then invocations count should be greater than zero
+	if m.funcDelete != nil && afterDeleteCounter < 1 {
+		m.t.Error("Expected call to PlaceImageRepositoryMock.Delete")
+	}
+
+	if !m.DeleteMock.invocationsDone() && afterDeleteCounter > 0 {
+		m.t.Errorf("Expected %d calls to PlaceImageRepositoryMock.Delete but found %d calls",
+			mm_atomic.LoadUint64(&m.DeleteMock.expectedInvocations), afterDeleteCounter)
+	}
+}
+
+type mPlaceImageRepositoryMockGetByPlaceID struct {
+	optional           bool
+	mock               *PlaceImageRepositoryMock
+	defaultExpectation *PlaceImageRepositoryMockGetByPlaceIDExpectation
+	expectations       []*PlaceImageRepositoryMockGetByPlaceIDExpectation
+
+	callArgs []*PlaceImageRepositoryMockGetByPlaceIDParams
+	mutex    sync.RWMutex
+
+	expectedInvocations uint64
+}
+
+// PlaceImageRepositoryMockGetByPlaceIDExpectation specifies expectation struct of the PlaceImageRepository.GetByPlaceID
+type PlaceImageRepositoryMockGetByPlaceIDExpectation struct {
+	mock      *PlaceImageRepositoryMock
+	params    *PlaceImageRepositoryMockGetByPlaceIDParams
+	paramPtrs *PlaceImageRepositoryMockGetByPlaceIDParamPtrs
+	results   *PlaceImageRepositoryMockGetByPlaceIDResults
+	Counter   uint64
+}
+
+// PlaceImageRepositoryMockGetByPlaceIDParams contains parameters of the PlaceImageRepository.GetByPlaceID
+type PlaceImageRepositoryMockGetByPlaceIDParams struct {
+	ctx     context.Context
+	placeID int
+}
+
+// PlaceImageRepositoryMockGetByPlaceIDParamPtrs contains pointers to parameters of the PlaceImageRepository.GetByPlaceID
+type PlaceImageRepositoryMockGetByPlaceIDParamPtrs struct {
+	ctx     *context.Context
+	placeID *int
+}
+
+// PlaceImageRepositoryMockGetByPlaceIDResults contains results of the PlaceImageRepository.GetByPlaceID
+type PlaceImageRepositoryMockGetByPlaceIDResults struct {
+	ia1 []models.Image
+	err error
+}
+
+// Marks this method to be optional. The default behavior of any method with Return() is '1 or more', meaning
+// the test will fail minimock's automatic final call check if the mocked method was not called at least once.
+// Optional() makes method check to work in '0 or more' mode.
+// It is NOT RECOMMENDED to use this option unless you really need it, as default behaviour helps to
+// catch the problems when the expected method call is totally skipped during test run.
+func (mmGetByPlaceID *mPlaceImageRepositoryMockGetByPlaceID) Optional() *mPlaceImageRepositoryMockGetByPlaceID {
+	mmGetByPlaceID.optional = true
+	return mmGetByPlaceID
+}
+
+// Expect sets up expected params for PlaceImageRepository.GetByPlaceID
+func (mmGetByPlaceID *mPlaceImageRepositoryMockGetByPlaceID) Expect(ctx context.Context, placeID int) *mPlaceImageRepositoryMockGetByPlaceID {
+	if mmGetByPlaceID.mock.funcGetByPlaceID != nil {
+		mmGetByPlaceID.mock.t.Fatalf("PlaceImageRepositoryMock.GetByPlaceID mock is already set by Set")
+	}
+
+	if mmGetByPlaceID.defaultExpectation == nil {
+		mmGetByPlaceID.defaultExpectation = &PlaceImageRepositoryMockGetByPlaceIDExpectation{}
+	}
+
+	if mmGetByPlaceID.defaultExpectation.paramPtrs != nil {
+		mmGetByPlaceID.mock.t.Fatalf("PlaceImageRepositoryMock.GetByPlaceID mock is already set by ExpectParams functions")
+	}
+
+	mmGetByPlaceID.defaultExpectation.params = &PlaceImageRepositoryMockGetByPlaceIDParams{ctx, placeID}
+	for _, e := range mmGetByPlaceID.expectations {
+		if minimock.Equal(e.params, mmGetByPlaceID.defaultExpectation.params) {
+			mmGetByPlaceID.mock.t.Fatalf("Expectation set by When has same params: %#v", *mmGetByPlaceID.defaultExpectation.params)
+		}
+	}
+
+	return mmGetByPlaceID
+}
+
+// ExpectCtxParam1 sets up expected param ctx for PlaceImageRepository.GetByPlaceID
+func (mmGetByPlaceID *mPlaceImageRepositoryMockGetByPlaceID) ExpectCtxParam1(ctx context.Context) *mPlaceImageRepositoryMockGetByPlaceID {
+	if mmGetByPlaceID.mock.funcGetByPlaceID != nil {
+		mmGetByPlaceID.mock.t.Fatalf("PlaceImageRepositoryMock.GetByPlaceID mock is already set by Set")
+	}
+
+	if mmGetByPlaceID.defaultExpectation == nil {
+		mmGetByPlaceID.defaultExpectation = &PlaceImageRepositoryMockGetByPlaceIDExpectation{}
+	}
+
+	if mmGetByPlaceID.defaultExpectation.params != nil {
+		mmGetByPlaceID.mock.t.Fatalf("PlaceImageRepositoryMock.GetByPlaceID mock is already set by Expect")
+	}
+
+	if mmGetByPlaceID.defaultExpectation.paramPtrs == nil {
+		mmGetByPlaceID.defaultExpectation.paramPtrs = &PlaceImageRepositoryMockGetByPlaceIDParamPtrs{}
+	}
+	mmGetByPlaceID.defaultExpectation.paramPtrs.ctx = &ctx
+
+	return mmGetByPlaceID
+}
+
+// ExpectPlaceIDParam2 sets up expected param placeID for PlaceImageRepository.GetByPlaceID
+func (mmGetByPlaceID *mPlaceImageRepositoryMockGetByPlaceID) ExpectPlaceIDParam2(placeID int) *mPlaceImageRepositoryMockGetByPlaceID {
+	if mmGetByPlaceID.mock.funcGetByPlaceID != nil {
+		mmGetByPlaceID.mock.t.Fatalf("PlaceImageRepositoryMock.GetByPlaceID mock is already set by Set")
+	}
+
+	if mmGetByPlaceID.defaultExpectation == nil {
+		mmGetByPlaceID.defaultExpectation = &PlaceImageRepositoryMockGetByPlaceIDExpectation{}
+	}
+
+	if mmGetByPlaceID.defaultExpectation.params != nil {
+		mmGetByPlaceID.mock.t.Fatalf("PlaceImageRepositoryMock.GetByPlaceID mock is already set by Expect")
+	}
+
+	if mmGetByPlaceID.defaultExpectation.paramPtrs == nil {
+		mmGetByPlaceID.defaultExpectation.paramPtrs = &PlaceImageRepositoryMockGetByPlaceIDParamPtrs{}
+	}
+	mmGetByPlaceID.defaultExpectation.paramPtrs.placeID = &placeID
+
+	return mmGetByPlaceID
+}
+
+// Inspect accepts an inspector function that has same arguments as the PlaceImageRepository.GetByPlaceID
+func (mmGetByPlaceID *mPlaceImageRepositoryMockGetByPlaceID) Inspect(f func(ctx context.Context, placeID int)) *mPlaceImageRepositoryMockGetByPlaceID {
+	if mmGetByPlaceID.mock.inspectFuncGetByPlaceID != nil {
+		mmGetByPlaceID.mock.t.Fatalf("Inspect function is already set for PlaceImageRepositoryMock.GetByPlaceID")
+	}
+
+	mmGetByPlaceID.mock.inspectFuncGetByPlaceID = f
+
+	return mmGetByPlaceID
+}
+
+// Return sets up results that will be returned by PlaceImageRepository.GetByPlaceID
+func (mmGetByPlaceID *mPlaceImageRepositoryMockGetByPlaceID) Return(ia1 []models.Image, err error) *PlaceImageRepositoryMock {
+	if mmGetByPlaceID.mock.funcGetByPlaceID != nil {
+		mmGetByPlaceID.mock.t.Fatalf("PlaceImageRepositoryMock.GetByPlaceID mock is already set by Set")
+	}
+
+	if mmGetByPlaceID.defaultExpectation == nil {
+		mmGetByPlaceID.defaultExpectation = &PlaceImageRepositoryMockGetByPlaceIDExpectation{mock: mmGetByPlaceID.mock}
+	}
+	mmGetByPlaceID.defaultExpectation.results = &PlaceImageRepositoryMockGetByPlaceIDResults{ia1, err}
+	return mmGetByPlaceID.mock
+}
+
+// Set uses given function f to mock the PlaceImageRepository.GetByPlaceID method
+func (mmGetByPlaceID *mPlaceImageRepositoryMockGetByPlaceID) Set(f func(ctx context.Context, placeID int) (ia1 []models.Image, err error)) *PlaceImageRepositoryMock {
+	if mmGetByPlaceID.defaultExpectation != nil {
+		mmGetByPlaceID.mock.t.Fatalf("Default expectation is already set for the PlaceImageRepository.GetByPlaceID method")
+	}
+
+	if len(mmGetByPlaceID.expectations) > 0 {
+		mmGetByPlaceID.mock.t.Fatalf("Some expectations are already set for the PlaceImageRepository.GetByPlaceID method")
+	}
+
+	mmGetByPlaceID.mock.funcGetByPlaceID = f
+	return mmGetByPlaceID.mock
+}
+
+// When sets expectation for the PlaceImageRepository.GetByPlaceID which will trigger the result defined by the following
+// Then helper
+func (mmGetByPlaceID *mPlaceImageRepositoryMockGetByPlaceID) When(ctx context.Context, placeID int) *PlaceImageRepositoryMockGetByPlaceIDExpectation {
+	if mmGetByPlaceID.mock.funcGetByPlaceID != nil {
+		mmGetByPlaceID.mock.t.Fatalf("PlaceImageRepositoryMock.GetByPlaceID mock is already set by Set")
+	}
+
+	expectation := &PlaceImageRepositoryMockGetByPlaceIDExpectation{
+		mock:   mmGetByPlaceID.mock,
+		params: &PlaceImageRepositoryMockGetByPlaceIDParams{ctx, placeID},
+	}
+	mmGetByPlaceID.expectations = append(mmGetByPlaceID.expectations, expectation)
+	return expectation
+}
+
+// Then sets up PlaceImageRepository.GetByPlaceID return parameters for the expectation previously defined by the When method
+func (e *PlaceImageRepositoryMockGetByPlaceIDExpectation) Then(ia1 []models.Image, err error) *PlaceImageRepositoryMock {
+	e.results = &PlaceImageRepositoryMockGetByPlaceIDResults{ia1, err}
+	return e.mock
+}
+
+// Times sets number of times PlaceImageRepository.GetByPlaceID should be invoked
+func (mmGetByPlaceID *mPlaceImageRepositoryMockGetByPlaceID) Times(n uint64) *mPlaceImageRepositoryMockGetByPlaceID {
+	if n == 0 {
+		mmGetByPlaceID.mock.t.Fatalf("Times of PlaceImageRepositoryMock.GetByPlaceID mock can not be zero")
+	}
+	mm_atomic.StoreUint64(&mmGetByPlaceID.expectedInvocations, n)
+	return mmGetByPlaceID
+}
+
+func (mmGetByPlaceID *mPlaceImageRepositoryMockGetByPlaceID) invocationsDone() bool {
+	if len(mmGetByPlaceID.expectations) == 0 && mmGetByPlaceID.defaultExpectation == nil && mmGetByPlaceID.mock.funcGetByPlaceID == nil {
+		return true
+	}
+
+	totalInvocations := mm_atomic.LoadUint64(&mmGetByPlaceID.mock.afterGetByPlaceIDCounter)
+	expectedInvocations := mm_atomic.LoadUint64(&mmGetByPlaceID.expectedInvocations)
+
+	return totalInvocations > 0 && (expectedInvocations == 0 || expectedInvocations == totalInvocations)
+}
+
+// GetByPlaceID implements place.PlaceImageRepository
+func (mmGetByPlaceID *PlaceImageRepositoryMock) GetByPlaceID(ctx context.Context, placeID int) (ia1 []models.Image, err error) {
+	mm_atomic.AddUint64(&mmGetByPlaceID.beforeGetByPlaceIDCounter, 1)
+	defer mm_atomic.AddUint64(&mmGetByPlaceID.afterGetByPlaceIDCounter, 1)
+
+	if mmGetByPlaceID.inspectFuncGetByPlaceID != nil {
+		mmGetByPlaceID.inspectFuncGetByPlaceID(ctx, placeID)
+	}
+
+	mm_params := PlaceImageRepositoryMockGetByPlaceIDParams{ctx, placeID}
+
+	// Record call args
+	mmGetByPlaceID.GetByPlaceIDMock.mutex.Lock()
+	mmGetByPlaceID.GetByPlaceIDMock.callArgs = append(mmGetByPlaceID.GetByPlaceIDMock.callArgs, &mm_params)
+	mmGetByPlaceID.GetByPlaceIDMock.mutex.Unlock()
+
+	for _, e := range mmGetByPlaceID.GetByPlaceIDMock.expectations {
+		if minimock.Equal(*e.params, mm_params) {
+			mm_atomic.AddUint64(&e.Counter, 1)
+			return e.results.ia1, e.results.err
+		}
+	}
+
+	if mmGetByPlaceID.GetByPlaceIDMock.defaultExpectation != nil {
+		mm_atomic.AddUint64(&mmGetByPlaceID.GetByPlaceIDMock.defaultExpectation.Counter, 1)
+		mm_want := mmGetByPlaceID.GetByPlaceIDMock.defaultExpectation.params
+		mm_want_ptrs := mmGetByPlaceID.GetByPlaceIDMock.defaultExpectation.paramPtrs
+
+		mm_got := PlaceImageRepositoryMockGetByPlaceIDParams{ctx, placeID}
+
+		if mm_want_ptrs != nil {
+
+			if mm_want_ptrs.ctx != nil && !minimock.Equal(*mm_want_ptrs.ctx, mm_got.ctx) {
+				mmGetByPlaceID.t.Errorf("PlaceImageRepositoryMock.GetByPlaceID got unexpected parameter ctx, want: %#v, got: %#v%s\n", *mm_want_ptrs.ctx, mm_got.ctx, minimock.Diff(*mm_want_ptrs.ctx, mm_got.ctx))
+			}
+
+			if mm_want_ptrs.placeID != nil && !minimock.Equal(*mm_want_ptrs.placeID, mm_got.placeID) {
+				mmGetByPlaceID.t.Errorf("PlaceImageRepositoryMock.GetByPlaceID got unexpected parameter placeID, want: %#v, got: %#v%s\n", *mm_want_ptrs.placeID, mm_got.placeID, minimock.Diff(*mm_want_ptrs.placeID, mm_got.placeID))
+			}
+
+		} else if mm_want != nil && !minimock.Equal(*mm_want, mm_got) {
+			mmGetByPlaceID.t.Errorf("PlaceImageRepositoryMock.GetByPlaceID got unexpected parameters, want: %#v, got: %#v%s\n", *mm_want, mm_got, minimock.Diff(*mm_want, mm_got))
+		}
+
+		mm_results := mmGetByPlaceID.GetByPlaceIDMock.defaultExpectation.results
+		if mm_results == nil {
+			mmGetByPlaceID.t.Fatal("No results are set for the PlaceImageRepositoryMock.GetByPlaceID")
+		}
+		return (*mm_results).ia1, (*mm_results).err
+	}
+	if mmGetByPlaceID.funcGetByPlaceID != nil {
+		return mmGetByPlaceID.funcGetByPlaceID(ctx, placeID)
+	}
+	mmGetByPlaceID.t.Fatalf("Unexpected call to PlaceImageRepositoryMock.GetByPlaceID. %v %v", ctx, placeID)
+	return
+}
+
+// GetByPlaceIDAfterCounter returns a count of finished PlaceImageRepositoryMock.GetByPlaceID invocations
+func (mmGetByPlaceID *PlaceImageRepositoryMock) GetByPlaceIDAfterCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmGetByPlaceID.afterGetByPlaceIDCounter)
+}
+
+// GetByPlaceIDBeforeCounter returns a count of PlaceImageRepositoryMock.GetByPlaceID invocations
+func (mmGetByPlaceID *PlaceImageRepositoryMock) GetByPlaceIDBeforeCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmGetByPlaceID.beforeGetByPlaceIDCounter)
+}
+
+// Calls returns a list of arguments used in each call to PlaceImageRepositoryMock.GetByPlaceID.
+// The list is in the same order as the calls were made (i.e. recent calls have a higher index)
+func (mmGetByPlaceID *mPlaceImageRepositoryMockGetByPlaceID) Calls() []*PlaceImageRepositoryMockGetByPlaceIDParams {
+	mmGetByPlaceID.mutex.RLock()
+
+	argCopy := make([]*PlaceImageRepositoryMockGetByPlaceIDParams, len(mmGetByPlaceID.callArgs))
+	copy(argCopy, mmGetByPlaceID.callArgs)
+
+	mmGetByPlaceID.mutex.RUnlock()
+
+	return argCopy
+}
+
+// MinimockGetByPlaceIDDone returns true if the count of the GetByPlaceID invocations corresponds
+// the number of defined expectations
+func (m *PlaceImageRepositoryMock) MinimockGetByPlaceIDDone() bool {
+	if m.GetByPlaceIDMock.optional {
+		// Optional methods provide '0 or more' call count restriction.
+		return true
+	}
+
+	for _, e := range m.GetByPlaceIDMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			return false
+		}
+	}
+
+	return m.GetByPlaceIDMock.invocationsDone()
+}
+
+// MinimockGetByPlaceIDInspect logs each unmet expectation
+func (m *PlaceImageRepositoryMock) MinimockGetByPlaceIDInspect() {
+	for _, e := range m.GetByPlaceIDMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			m.t.Errorf("Expected call to PlaceImageRepositoryMock.GetByPlaceID with params: %#v", *e.params)
+		}
+	}
+
+	afterGetByPlaceIDCounter := mm_atomic.LoadUint64(&m.afterGetByPlaceIDCounter)
+	// if default expectation was set then invocations count should be greater than zero
+	if m.GetByPlaceIDMock.defaultExpectation != nil && afterGetByPlaceIDCounter < 1 {
+		if m.GetByPlaceIDMock.defaultExpectation.params == nil {
+			m.t.Error("Expected call to PlaceImageRepositoryMock.GetByPlaceID")
+		} else {
+			m.t.Errorf("Expected call to PlaceImageRepositoryMock.GetByPlaceID with params: %#v", *m.GetByPlaceIDMock.defaultExpectation.params)
+		}
+	}
+	// if func was set then invocations count should be greater than zero
+	if m.funcGetByPlaceID != nil && afterGetByPlaceIDCounter < 1 {
+		m.t.Error("Expected call to PlaceImageRepositoryMock.GetByPlaceID")
+	}
+
+	if !m.GetByPlaceIDMock.invocationsDone() && afterGetByPlaceIDCounter > 0 {
+		m.t.Errorf("Expected %d calls to PlaceImageRepositoryMock.GetByPlaceID but found %d calls",
+			mm_atomic.LoadUint64(&m.GetByPlaceIDMock.expectedInvocations), afterGetByPlaceIDCounter)
+	}
+}
+
+// MinimockFinish checks that all mocked methods have been called the expected number of times
+func (m *PlaceImageRepositoryMock) MinimockFinish() {
+	m.finishOnce.Do(func() {
+		if !m.minimockDone() {
+			m.MinimockDeleteInspect()
+
+			m.MinimockGetByPlaceIDInspect()
+		}
+	})
+}
+
+// MinimockWait waits for all mocked methods to be called the expected number of times
+func (m *PlaceImageRepositoryMock) MinimockWait(timeout mm_time.Duration) {
+	timeoutCh := mm_time.After(timeout)
+	for {
+		if m.minimockDone() {
+			return
+		}
+		select {
+		case <-timeoutCh:
+			m.MinimockFinish()
+			return
+		case <-mm_time.After(10 * mm_time.Millisecond):
+		}
+	}
+}
+
+func (m *PlaceImageRepositoryMock) minimockDone() bool {
+	done := true
+	return done &&
+		m.MinimockDeleteDone() &&
+		m.MinimockGetByPlaceIDDone()
+}

File diff ditekan karena terlalu besar
+ 525 - 84
internal/api/v1/place/mocks/place_repository_minimock.go


+ 422 - 0
internal/api/v1/place/mocks/place_thing_repository_minimock.go

@@ -0,0 +1,422 @@
+// Code generated by http://github.com/gojuno/minimock (v3.3.13). DO NOT EDIT.
+
+package mocks
+
+//go:generate minimock -i git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/place.PlaceThingRepository -o place_thing_repository_minimock.go -n PlaceThingRepositoryMock -p mocks
+
+import (
+	"context"
+	"database/sql"
+	"sync"
+	mm_atomic "sync/atomic"
+	mm_time "time"
+
+	"github.com/gojuno/minimock/v3"
+)
+
+// PlaceThingRepositoryMock implements place.PlaceThingRepository
+type PlaceThingRepositoryMock struct {
+	t          minimock.Tester
+	finishOnce sync.Once
+
+	funcDeleteThing          func(ctx context.Context, thingID int, tx *sql.Tx) (err error)
+	inspectFuncDeleteThing   func(ctx context.Context, thingID int, tx *sql.Tx)
+	afterDeleteThingCounter  uint64
+	beforeDeleteThingCounter uint64
+	DeleteThingMock          mPlaceThingRepositoryMockDeleteThing
+}
+
+// NewPlaceThingRepositoryMock returns a mock for place.PlaceThingRepository
+func NewPlaceThingRepositoryMock(t minimock.Tester) *PlaceThingRepositoryMock {
+	m := &PlaceThingRepositoryMock{t: t}
+
+	if controller, ok := t.(minimock.MockController); ok {
+		controller.RegisterMocker(m)
+	}
+
+	m.DeleteThingMock = mPlaceThingRepositoryMockDeleteThing{mock: m}
+	m.DeleteThingMock.callArgs = []*PlaceThingRepositoryMockDeleteThingParams{}
+
+	t.Cleanup(m.MinimockFinish)
+
+	return m
+}
+
+type mPlaceThingRepositoryMockDeleteThing struct {
+	optional           bool
+	mock               *PlaceThingRepositoryMock
+	defaultExpectation *PlaceThingRepositoryMockDeleteThingExpectation
+	expectations       []*PlaceThingRepositoryMockDeleteThingExpectation
+
+	callArgs []*PlaceThingRepositoryMockDeleteThingParams
+	mutex    sync.RWMutex
+
+	expectedInvocations uint64
+}
+
+// PlaceThingRepositoryMockDeleteThingExpectation specifies expectation struct of the PlaceThingRepository.DeleteThing
+type PlaceThingRepositoryMockDeleteThingExpectation struct {
+	mock      *PlaceThingRepositoryMock
+	params    *PlaceThingRepositoryMockDeleteThingParams
+	paramPtrs *PlaceThingRepositoryMockDeleteThingParamPtrs
+	results   *PlaceThingRepositoryMockDeleteThingResults
+	Counter   uint64
+}
+
+// PlaceThingRepositoryMockDeleteThingParams contains parameters of the PlaceThingRepository.DeleteThing
+type PlaceThingRepositoryMockDeleteThingParams struct {
+	ctx     context.Context
+	thingID int
+	tx      *sql.Tx
+}
+
+// PlaceThingRepositoryMockDeleteThingParamPtrs contains pointers to parameters of the PlaceThingRepository.DeleteThing
+type PlaceThingRepositoryMockDeleteThingParamPtrs struct {
+	ctx     *context.Context
+	thingID *int
+	tx      **sql.Tx
+}
+
+// PlaceThingRepositoryMockDeleteThingResults contains results of the PlaceThingRepository.DeleteThing
+type PlaceThingRepositoryMockDeleteThingResults struct {
+	err error
+}
+
+// Marks this method to be optional. The default behavior of any method with Return() is '1 or more', meaning
+// the test will fail minimock's automatic final call check if the mocked method was not called at least once.
+// Optional() makes method check to work in '0 or more' mode.
+// It is NOT RECOMMENDED to use this option unless you really need it, as default behaviour helps to
+// catch the problems when the expected method call is totally skipped during test run.
+func (mmDeleteThing *mPlaceThingRepositoryMockDeleteThing) Optional() *mPlaceThingRepositoryMockDeleteThing {
+	mmDeleteThing.optional = true
+	return mmDeleteThing
+}
+
+// Expect sets up expected params for PlaceThingRepository.DeleteThing
+func (mmDeleteThing *mPlaceThingRepositoryMockDeleteThing) Expect(ctx context.Context, thingID int, tx *sql.Tx) *mPlaceThingRepositoryMockDeleteThing {
+	if mmDeleteThing.mock.funcDeleteThing != nil {
+		mmDeleteThing.mock.t.Fatalf("PlaceThingRepositoryMock.DeleteThing mock is already set by Set")
+	}
+
+	if mmDeleteThing.defaultExpectation == nil {
+		mmDeleteThing.defaultExpectation = &PlaceThingRepositoryMockDeleteThingExpectation{}
+	}
+
+	if mmDeleteThing.defaultExpectation.paramPtrs != nil {
+		mmDeleteThing.mock.t.Fatalf("PlaceThingRepositoryMock.DeleteThing mock is already set by ExpectParams functions")
+	}
+
+	mmDeleteThing.defaultExpectation.params = &PlaceThingRepositoryMockDeleteThingParams{ctx, thingID, tx}
+	for _, e := range mmDeleteThing.expectations {
+		if minimock.Equal(e.params, mmDeleteThing.defaultExpectation.params) {
+			mmDeleteThing.mock.t.Fatalf("Expectation set by When has same params: %#v", *mmDeleteThing.defaultExpectation.params)
+		}
+	}
+
+	return mmDeleteThing
+}
+
+// ExpectCtxParam1 sets up expected param ctx for PlaceThingRepository.DeleteThing
+func (mmDeleteThing *mPlaceThingRepositoryMockDeleteThing) ExpectCtxParam1(ctx context.Context) *mPlaceThingRepositoryMockDeleteThing {
+	if mmDeleteThing.mock.funcDeleteThing != nil {
+		mmDeleteThing.mock.t.Fatalf("PlaceThingRepositoryMock.DeleteThing mock is already set by Set")
+	}
+
+	if mmDeleteThing.defaultExpectation == nil {
+		mmDeleteThing.defaultExpectation = &PlaceThingRepositoryMockDeleteThingExpectation{}
+	}
+
+	if mmDeleteThing.defaultExpectation.params != nil {
+		mmDeleteThing.mock.t.Fatalf("PlaceThingRepositoryMock.DeleteThing mock is already set by Expect")
+	}
+
+	if mmDeleteThing.defaultExpectation.paramPtrs == nil {
+		mmDeleteThing.defaultExpectation.paramPtrs = &PlaceThingRepositoryMockDeleteThingParamPtrs{}
+	}
+	mmDeleteThing.defaultExpectation.paramPtrs.ctx = &ctx
+
+	return mmDeleteThing
+}
+
+// ExpectThingIDParam2 sets up expected param thingID for PlaceThingRepository.DeleteThing
+func (mmDeleteThing *mPlaceThingRepositoryMockDeleteThing) ExpectThingIDParam2(thingID int) *mPlaceThingRepositoryMockDeleteThing {
+	if mmDeleteThing.mock.funcDeleteThing != nil {
+		mmDeleteThing.mock.t.Fatalf("PlaceThingRepositoryMock.DeleteThing mock is already set by Set")
+	}
+
+	if mmDeleteThing.defaultExpectation == nil {
+		mmDeleteThing.defaultExpectation = &PlaceThingRepositoryMockDeleteThingExpectation{}
+	}
+
+	if mmDeleteThing.defaultExpectation.params != nil {
+		mmDeleteThing.mock.t.Fatalf("PlaceThingRepositoryMock.DeleteThing mock is already set by Expect")
+	}
+
+	if mmDeleteThing.defaultExpectation.paramPtrs == nil {
+		mmDeleteThing.defaultExpectation.paramPtrs = &PlaceThingRepositoryMockDeleteThingParamPtrs{}
+	}
+	mmDeleteThing.defaultExpectation.paramPtrs.thingID = &thingID
+
+	return mmDeleteThing
+}
+
+// ExpectTxParam3 sets up expected param tx for PlaceThingRepository.DeleteThing
+func (mmDeleteThing *mPlaceThingRepositoryMockDeleteThing) ExpectTxParam3(tx *sql.Tx) *mPlaceThingRepositoryMockDeleteThing {
+	if mmDeleteThing.mock.funcDeleteThing != nil {
+		mmDeleteThing.mock.t.Fatalf("PlaceThingRepositoryMock.DeleteThing mock is already set by Set")
+	}
+
+	if mmDeleteThing.defaultExpectation == nil {
+		mmDeleteThing.defaultExpectation = &PlaceThingRepositoryMockDeleteThingExpectation{}
+	}
+
+	if mmDeleteThing.defaultExpectation.params != nil {
+		mmDeleteThing.mock.t.Fatalf("PlaceThingRepositoryMock.DeleteThing mock is already set by Expect")
+	}
+
+	if mmDeleteThing.defaultExpectation.paramPtrs == nil {
+		mmDeleteThing.defaultExpectation.paramPtrs = &PlaceThingRepositoryMockDeleteThingParamPtrs{}
+	}
+	mmDeleteThing.defaultExpectation.paramPtrs.tx = &tx
+
+	return mmDeleteThing
+}
+
+// Inspect accepts an inspector function that has same arguments as the PlaceThingRepository.DeleteThing
+func (mmDeleteThing *mPlaceThingRepositoryMockDeleteThing) Inspect(f func(ctx context.Context, thingID int, tx *sql.Tx)) *mPlaceThingRepositoryMockDeleteThing {
+	if mmDeleteThing.mock.inspectFuncDeleteThing != nil {
+		mmDeleteThing.mock.t.Fatalf("Inspect function is already set for PlaceThingRepositoryMock.DeleteThing")
+	}
+
+	mmDeleteThing.mock.inspectFuncDeleteThing = f
+
+	return mmDeleteThing
+}
+
+// Return sets up results that will be returned by PlaceThingRepository.DeleteThing
+func (mmDeleteThing *mPlaceThingRepositoryMockDeleteThing) Return(err error) *PlaceThingRepositoryMock {
+	if mmDeleteThing.mock.funcDeleteThing != nil {
+		mmDeleteThing.mock.t.Fatalf("PlaceThingRepositoryMock.DeleteThing mock is already set by Set")
+	}
+
+	if mmDeleteThing.defaultExpectation == nil {
+		mmDeleteThing.defaultExpectation = &PlaceThingRepositoryMockDeleteThingExpectation{mock: mmDeleteThing.mock}
+	}
+	mmDeleteThing.defaultExpectation.results = &PlaceThingRepositoryMockDeleteThingResults{err}
+	return mmDeleteThing.mock
+}
+
+// Set uses given function f to mock the PlaceThingRepository.DeleteThing method
+func (mmDeleteThing *mPlaceThingRepositoryMockDeleteThing) Set(f func(ctx context.Context, thingID int, tx *sql.Tx) (err error)) *PlaceThingRepositoryMock {
+	if mmDeleteThing.defaultExpectation != nil {
+		mmDeleteThing.mock.t.Fatalf("Default expectation is already set for the PlaceThingRepository.DeleteThing method")
+	}
+
+	if len(mmDeleteThing.expectations) > 0 {
+		mmDeleteThing.mock.t.Fatalf("Some expectations are already set for the PlaceThingRepository.DeleteThing method")
+	}
+
+	mmDeleteThing.mock.funcDeleteThing = f
+	return mmDeleteThing.mock
+}
+
+// When sets expectation for the PlaceThingRepository.DeleteThing which will trigger the result defined by the following
+// Then helper
+func (mmDeleteThing *mPlaceThingRepositoryMockDeleteThing) When(ctx context.Context, thingID int, tx *sql.Tx) *PlaceThingRepositoryMockDeleteThingExpectation {
+	if mmDeleteThing.mock.funcDeleteThing != nil {
+		mmDeleteThing.mock.t.Fatalf("PlaceThingRepositoryMock.DeleteThing mock is already set by Set")
+	}
+
+	expectation := &PlaceThingRepositoryMockDeleteThingExpectation{
+		mock:   mmDeleteThing.mock,
+		params: &PlaceThingRepositoryMockDeleteThingParams{ctx, thingID, tx},
+	}
+	mmDeleteThing.expectations = append(mmDeleteThing.expectations, expectation)
+	return expectation
+}
+
+// Then sets up PlaceThingRepository.DeleteThing return parameters for the expectation previously defined by the When method
+func (e *PlaceThingRepositoryMockDeleteThingExpectation) Then(err error) *PlaceThingRepositoryMock {
+	e.results = &PlaceThingRepositoryMockDeleteThingResults{err}
+	return e.mock
+}
+
+// Times sets number of times PlaceThingRepository.DeleteThing should be invoked
+func (mmDeleteThing *mPlaceThingRepositoryMockDeleteThing) Times(n uint64) *mPlaceThingRepositoryMockDeleteThing {
+	if n == 0 {
+		mmDeleteThing.mock.t.Fatalf("Times of PlaceThingRepositoryMock.DeleteThing mock can not be zero")
+	}
+	mm_atomic.StoreUint64(&mmDeleteThing.expectedInvocations, n)
+	return mmDeleteThing
+}
+
+func (mmDeleteThing *mPlaceThingRepositoryMockDeleteThing) invocationsDone() bool {
+	if len(mmDeleteThing.expectations) == 0 && mmDeleteThing.defaultExpectation == nil && mmDeleteThing.mock.funcDeleteThing == nil {
+		return true
+	}
+
+	totalInvocations := mm_atomic.LoadUint64(&mmDeleteThing.mock.afterDeleteThingCounter)
+	expectedInvocations := mm_atomic.LoadUint64(&mmDeleteThing.expectedInvocations)
+
+	return totalInvocations > 0 && (expectedInvocations == 0 || expectedInvocations == totalInvocations)
+}
+
+// DeleteThing implements place.PlaceThingRepository
+func (mmDeleteThing *PlaceThingRepositoryMock) DeleteThing(ctx context.Context, thingID int, tx *sql.Tx) (err error) {
+	mm_atomic.AddUint64(&mmDeleteThing.beforeDeleteThingCounter, 1)
+	defer mm_atomic.AddUint64(&mmDeleteThing.afterDeleteThingCounter, 1)
+
+	if mmDeleteThing.inspectFuncDeleteThing != nil {
+		mmDeleteThing.inspectFuncDeleteThing(ctx, thingID, tx)
+	}
+
+	mm_params := PlaceThingRepositoryMockDeleteThingParams{ctx, thingID, tx}
+
+	// Record call args
+	mmDeleteThing.DeleteThingMock.mutex.Lock()
+	mmDeleteThing.DeleteThingMock.callArgs = append(mmDeleteThing.DeleteThingMock.callArgs, &mm_params)
+	mmDeleteThing.DeleteThingMock.mutex.Unlock()
+
+	for _, e := range mmDeleteThing.DeleteThingMock.expectations {
+		if minimock.Equal(*e.params, mm_params) {
+			mm_atomic.AddUint64(&e.Counter, 1)
+			return e.results.err
+		}
+	}
+
+	if mmDeleteThing.DeleteThingMock.defaultExpectation != nil {
+		mm_atomic.AddUint64(&mmDeleteThing.DeleteThingMock.defaultExpectation.Counter, 1)
+		mm_want := mmDeleteThing.DeleteThingMock.defaultExpectation.params
+		mm_want_ptrs := mmDeleteThing.DeleteThingMock.defaultExpectation.paramPtrs
+
+		mm_got := PlaceThingRepositoryMockDeleteThingParams{ctx, thingID, tx}
+
+		if mm_want_ptrs != nil {
+
+			if mm_want_ptrs.ctx != nil && !minimock.Equal(*mm_want_ptrs.ctx, mm_got.ctx) {
+				mmDeleteThing.t.Errorf("PlaceThingRepositoryMock.DeleteThing got unexpected parameter ctx, want: %#v, got: %#v%s\n", *mm_want_ptrs.ctx, mm_got.ctx, minimock.Diff(*mm_want_ptrs.ctx, mm_got.ctx))
+			}
+
+			if mm_want_ptrs.thingID != nil && !minimock.Equal(*mm_want_ptrs.thingID, mm_got.thingID) {
+				mmDeleteThing.t.Errorf("PlaceThingRepositoryMock.DeleteThing got unexpected parameter thingID, want: %#v, got: %#v%s\n", *mm_want_ptrs.thingID, mm_got.thingID, minimock.Diff(*mm_want_ptrs.thingID, mm_got.thingID))
+			}
+
+			if mm_want_ptrs.tx != nil && !minimock.Equal(*mm_want_ptrs.tx, mm_got.tx) {
+				mmDeleteThing.t.Errorf("PlaceThingRepositoryMock.DeleteThing got unexpected parameter tx, want: %#v, got: %#v%s\n", *mm_want_ptrs.tx, mm_got.tx, minimock.Diff(*mm_want_ptrs.tx, mm_got.tx))
+			}
+
+		} else if mm_want != nil && !minimock.Equal(*mm_want, mm_got) {
+			mmDeleteThing.t.Errorf("PlaceThingRepositoryMock.DeleteThing got unexpected parameters, want: %#v, got: %#v%s\n", *mm_want, mm_got, minimock.Diff(*mm_want, mm_got))
+		}
+
+		mm_results := mmDeleteThing.DeleteThingMock.defaultExpectation.results
+		if mm_results == nil {
+			mmDeleteThing.t.Fatal("No results are set for the PlaceThingRepositoryMock.DeleteThing")
+		}
+		return (*mm_results).err
+	}
+	if mmDeleteThing.funcDeleteThing != nil {
+		return mmDeleteThing.funcDeleteThing(ctx, thingID, tx)
+	}
+	mmDeleteThing.t.Fatalf("Unexpected call to PlaceThingRepositoryMock.DeleteThing. %v %v %v", ctx, thingID, tx)
+	return
+}
+
+// DeleteThingAfterCounter returns a count of finished PlaceThingRepositoryMock.DeleteThing invocations
+func (mmDeleteThing *PlaceThingRepositoryMock) DeleteThingAfterCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmDeleteThing.afterDeleteThingCounter)
+}
+
+// DeleteThingBeforeCounter returns a count of PlaceThingRepositoryMock.DeleteThing invocations
+func (mmDeleteThing *PlaceThingRepositoryMock) DeleteThingBeforeCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmDeleteThing.beforeDeleteThingCounter)
+}
+
+// Calls returns a list of arguments used in each call to PlaceThingRepositoryMock.DeleteThing.
+// The list is in the same order as the calls were made (i.e. recent calls have a higher index)
+func (mmDeleteThing *mPlaceThingRepositoryMockDeleteThing) Calls() []*PlaceThingRepositoryMockDeleteThingParams {
+	mmDeleteThing.mutex.RLock()
+
+	argCopy := make([]*PlaceThingRepositoryMockDeleteThingParams, len(mmDeleteThing.callArgs))
+	copy(argCopy, mmDeleteThing.callArgs)
+
+	mmDeleteThing.mutex.RUnlock()
+
+	return argCopy
+}
+
+// MinimockDeleteThingDone returns true if the count of the DeleteThing invocations corresponds
+// the number of defined expectations
+func (m *PlaceThingRepositoryMock) MinimockDeleteThingDone() bool {
+	if m.DeleteThingMock.optional {
+		// Optional methods provide '0 or more' call count restriction.
+		return true
+	}
+
+	for _, e := range m.DeleteThingMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			return false
+		}
+	}
+
+	return m.DeleteThingMock.invocationsDone()
+}
+
+// MinimockDeleteThingInspect logs each unmet expectation
+func (m *PlaceThingRepositoryMock) MinimockDeleteThingInspect() {
+	for _, e := range m.DeleteThingMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			m.t.Errorf("Expected call to PlaceThingRepositoryMock.DeleteThing with params: %#v", *e.params)
+		}
+	}
+
+	afterDeleteThingCounter := mm_atomic.LoadUint64(&m.afterDeleteThingCounter)
+	// if default expectation was set then invocations count should be greater than zero
+	if m.DeleteThingMock.defaultExpectation != nil && afterDeleteThingCounter < 1 {
+		if m.DeleteThingMock.defaultExpectation.params == nil {
+			m.t.Error("Expected call to PlaceThingRepositoryMock.DeleteThing")
+		} else {
+			m.t.Errorf("Expected call to PlaceThingRepositoryMock.DeleteThing with params: %#v", *m.DeleteThingMock.defaultExpectation.params)
+		}
+	}
+	// if func was set then invocations count should be greater than zero
+	if m.funcDeleteThing != nil && afterDeleteThingCounter < 1 {
+		m.t.Error("Expected call to PlaceThingRepositoryMock.DeleteThing")
+	}
+
+	if !m.DeleteThingMock.invocationsDone() && afterDeleteThingCounter > 0 {
+		m.t.Errorf("Expected %d calls to PlaceThingRepositoryMock.DeleteThing but found %d calls",
+			mm_atomic.LoadUint64(&m.DeleteThingMock.expectedInvocations), afterDeleteThingCounter)
+	}
+}
+
+// MinimockFinish checks that all mocked methods have been called the expected number of times
+func (m *PlaceThingRepositoryMock) MinimockFinish() {
+	m.finishOnce.Do(func() {
+		if !m.minimockDone() {
+			m.MinimockDeleteThingInspect()
+		}
+	})
+}
+
+// MinimockWait waits for all mocked methods to be called the expected number of times
+func (m *PlaceThingRepositoryMock) MinimockWait(timeout mm_time.Duration) {
+	timeoutCh := mm_time.After(timeout)
+	for {
+		if m.minimockDone() {
+			return
+		}
+		select {
+		case <-timeoutCh:
+			m.MinimockFinish()
+			return
+		case <-mm_time.After(10 * mm_time.Millisecond):
+		}
+	}
+}
+
+func (m *PlaceThingRepositoryMock) minimockDone() bool {
+	done := true
+	return done &&
+		m.MinimockDeleteThingDone()
+}

+ 756 - 0
internal/api/v1/place/mocks/thing_image_repository_minimock.go

@@ -0,0 +1,756 @@
+// Code generated by http://github.com/gojuno/minimock (v3.3.13). DO NOT EDIT.
+
+package mocks
+
+//go:generate minimock -i git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/place.ThingImageRepository -o thing_image_repository_minimock.go -n ThingImageRepositoryMock -p mocks
+
+import (
+	"context"
+	"database/sql"
+	"sync"
+	mm_atomic "sync/atomic"
+	mm_time "time"
+
+	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
+	"github.com/gojuno/minimock/v3"
+)
+
+// ThingImageRepositoryMock implements place.ThingImageRepository
+type ThingImageRepositoryMock struct {
+	t          minimock.Tester
+	finishOnce sync.Once
+
+	funcDelete          func(ctx context.Context, imageID int, tx *sql.Tx) (err error)
+	inspectFuncDelete   func(ctx context.Context, imageID int, tx *sql.Tx)
+	afterDeleteCounter  uint64
+	beforeDeleteCounter uint64
+	DeleteMock          mThingImageRepositoryMockDelete
+
+	funcGetByThingID          func(ctx context.Context, thingID int) (ia1 []models.Image, err error)
+	inspectFuncGetByThingID   func(ctx context.Context, thingID int)
+	afterGetByThingIDCounter  uint64
+	beforeGetByThingIDCounter uint64
+	GetByThingIDMock          mThingImageRepositoryMockGetByThingID
+}
+
+// NewThingImageRepositoryMock returns a mock for place.ThingImageRepository
+func NewThingImageRepositoryMock(t minimock.Tester) *ThingImageRepositoryMock {
+	m := &ThingImageRepositoryMock{t: t}
+
+	if controller, ok := t.(minimock.MockController); ok {
+		controller.RegisterMocker(m)
+	}
+
+	m.DeleteMock = mThingImageRepositoryMockDelete{mock: m}
+	m.DeleteMock.callArgs = []*ThingImageRepositoryMockDeleteParams{}
+
+	m.GetByThingIDMock = mThingImageRepositoryMockGetByThingID{mock: m}
+	m.GetByThingIDMock.callArgs = []*ThingImageRepositoryMockGetByThingIDParams{}
+
+	t.Cleanup(m.MinimockFinish)
+
+	return m
+}
+
+type mThingImageRepositoryMockDelete struct {
+	optional           bool
+	mock               *ThingImageRepositoryMock
+	defaultExpectation *ThingImageRepositoryMockDeleteExpectation
+	expectations       []*ThingImageRepositoryMockDeleteExpectation
+
+	callArgs []*ThingImageRepositoryMockDeleteParams
+	mutex    sync.RWMutex
+
+	expectedInvocations uint64
+}
+
+// ThingImageRepositoryMockDeleteExpectation specifies expectation struct of the ThingImageRepository.Delete
+type ThingImageRepositoryMockDeleteExpectation struct {
+	mock      *ThingImageRepositoryMock
+	params    *ThingImageRepositoryMockDeleteParams
+	paramPtrs *ThingImageRepositoryMockDeleteParamPtrs
+	results   *ThingImageRepositoryMockDeleteResults
+	Counter   uint64
+}
+
+// ThingImageRepositoryMockDeleteParams contains parameters of the ThingImageRepository.Delete
+type ThingImageRepositoryMockDeleteParams struct {
+	ctx     context.Context
+	imageID int
+	tx      *sql.Tx
+}
+
+// ThingImageRepositoryMockDeleteParamPtrs contains pointers to parameters of the ThingImageRepository.Delete
+type ThingImageRepositoryMockDeleteParamPtrs struct {
+	ctx     *context.Context
+	imageID *int
+	tx      **sql.Tx
+}
+
+// ThingImageRepositoryMockDeleteResults contains results of the ThingImageRepository.Delete
+type ThingImageRepositoryMockDeleteResults struct {
+	err error
+}
+
+// Marks this method to be optional. The default behavior of any method with Return() is '1 or more', meaning
+// the test will fail minimock's automatic final call check if the mocked method was not called at least once.
+// Optional() makes method check to work in '0 or more' mode.
+// It is NOT RECOMMENDED to use this option unless you really need it, as default behaviour helps to
+// catch the problems when the expected method call is totally skipped during test run.
+func (mmDelete *mThingImageRepositoryMockDelete) Optional() *mThingImageRepositoryMockDelete {
+	mmDelete.optional = true
+	return mmDelete
+}
+
+// Expect sets up expected params for ThingImageRepository.Delete
+func (mmDelete *mThingImageRepositoryMockDelete) Expect(ctx context.Context, imageID int, tx *sql.Tx) *mThingImageRepositoryMockDelete {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("ThingImageRepositoryMock.Delete mock is already set by Set")
+	}
+
+	if mmDelete.defaultExpectation == nil {
+		mmDelete.defaultExpectation = &ThingImageRepositoryMockDeleteExpectation{}
+	}
+
+	if mmDelete.defaultExpectation.paramPtrs != nil {
+		mmDelete.mock.t.Fatalf("ThingImageRepositoryMock.Delete mock is already set by ExpectParams functions")
+	}
+
+	mmDelete.defaultExpectation.params = &ThingImageRepositoryMockDeleteParams{ctx, imageID, tx}
+	for _, e := range mmDelete.expectations {
+		if minimock.Equal(e.params, mmDelete.defaultExpectation.params) {
+			mmDelete.mock.t.Fatalf("Expectation set by When has same params: %#v", *mmDelete.defaultExpectation.params)
+		}
+	}
+
+	return mmDelete
+}
+
+// ExpectCtxParam1 sets up expected param ctx for ThingImageRepository.Delete
+func (mmDelete *mThingImageRepositoryMockDelete) ExpectCtxParam1(ctx context.Context) *mThingImageRepositoryMockDelete {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("ThingImageRepositoryMock.Delete mock is already set by Set")
+	}
+
+	if mmDelete.defaultExpectation == nil {
+		mmDelete.defaultExpectation = &ThingImageRepositoryMockDeleteExpectation{}
+	}
+
+	if mmDelete.defaultExpectation.params != nil {
+		mmDelete.mock.t.Fatalf("ThingImageRepositoryMock.Delete mock is already set by Expect")
+	}
+
+	if mmDelete.defaultExpectation.paramPtrs == nil {
+		mmDelete.defaultExpectation.paramPtrs = &ThingImageRepositoryMockDeleteParamPtrs{}
+	}
+	mmDelete.defaultExpectation.paramPtrs.ctx = &ctx
+
+	return mmDelete
+}
+
+// ExpectImageIDParam2 sets up expected param imageID for ThingImageRepository.Delete
+func (mmDelete *mThingImageRepositoryMockDelete) ExpectImageIDParam2(imageID int) *mThingImageRepositoryMockDelete {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("ThingImageRepositoryMock.Delete mock is already set by Set")
+	}
+
+	if mmDelete.defaultExpectation == nil {
+		mmDelete.defaultExpectation = &ThingImageRepositoryMockDeleteExpectation{}
+	}
+
+	if mmDelete.defaultExpectation.params != nil {
+		mmDelete.mock.t.Fatalf("ThingImageRepositoryMock.Delete mock is already set by Expect")
+	}
+
+	if mmDelete.defaultExpectation.paramPtrs == nil {
+		mmDelete.defaultExpectation.paramPtrs = &ThingImageRepositoryMockDeleteParamPtrs{}
+	}
+	mmDelete.defaultExpectation.paramPtrs.imageID = &imageID
+
+	return mmDelete
+}
+
+// ExpectTxParam3 sets up expected param tx for ThingImageRepository.Delete
+func (mmDelete *mThingImageRepositoryMockDelete) ExpectTxParam3(tx *sql.Tx) *mThingImageRepositoryMockDelete {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("ThingImageRepositoryMock.Delete mock is already set by Set")
+	}
+
+	if mmDelete.defaultExpectation == nil {
+		mmDelete.defaultExpectation = &ThingImageRepositoryMockDeleteExpectation{}
+	}
+
+	if mmDelete.defaultExpectation.params != nil {
+		mmDelete.mock.t.Fatalf("ThingImageRepositoryMock.Delete mock is already set by Expect")
+	}
+
+	if mmDelete.defaultExpectation.paramPtrs == nil {
+		mmDelete.defaultExpectation.paramPtrs = &ThingImageRepositoryMockDeleteParamPtrs{}
+	}
+	mmDelete.defaultExpectation.paramPtrs.tx = &tx
+
+	return mmDelete
+}
+
+// Inspect accepts an inspector function that has same arguments as the ThingImageRepository.Delete
+func (mmDelete *mThingImageRepositoryMockDelete) Inspect(f func(ctx context.Context, imageID int, tx *sql.Tx)) *mThingImageRepositoryMockDelete {
+	if mmDelete.mock.inspectFuncDelete != nil {
+		mmDelete.mock.t.Fatalf("Inspect function is already set for ThingImageRepositoryMock.Delete")
+	}
+
+	mmDelete.mock.inspectFuncDelete = f
+
+	return mmDelete
+}
+
+// Return sets up results that will be returned by ThingImageRepository.Delete
+func (mmDelete *mThingImageRepositoryMockDelete) Return(err error) *ThingImageRepositoryMock {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("ThingImageRepositoryMock.Delete mock is already set by Set")
+	}
+
+	if mmDelete.defaultExpectation == nil {
+		mmDelete.defaultExpectation = &ThingImageRepositoryMockDeleteExpectation{mock: mmDelete.mock}
+	}
+	mmDelete.defaultExpectation.results = &ThingImageRepositoryMockDeleteResults{err}
+	return mmDelete.mock
+}
+
+// Set uses given function f to mock the ThingImageRepository.Delete method
+func (mmDelete *mThingImageRepositoryMockDelete) Set(f func(ctx context.Context, imageID int, tx *sql.Tx) (err error)) *ThingImageRepositoryMock {
+	if mmDelete.defaultExpectation != nil {
+		mmDelete.mock.t.Fatalf("Default expectation is already set for the ThingImageRepository.Delete method")
+	}
+
+	if len(mmDelete.expectations) > 0 {
+		mmDelete.mock.t.Fatalf("Some expectations are already set for the ThingImageRepository.Delete method")
+	}
+
+	mmDelete.mock.funcDelete = f
+	return mmDelete.mock
+}
+
+// When sets expectation for the ThingImageRepository.Delete which will trigger the result defined by the following
+// Then helper
+func (mmDelete *mThingImageRepositoryMockDelete) When(ctx context.Context, imageID int, tx *sql.Tx) *ThingImageRepositoryMockDeleteExpectation {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("ThingImageRepositoryMock.Delete mock is already set by Set")
+	}
+
+	expectation := &ThingImageRepositoryMockDeleteExpectation{
+		mock:   mmDelete.mock,
+		params: &ThingImageRepositoryMockDeleteParams{ctx, imageID, tx},
+	}
+	mmDelete.expectations = append(mmDelete.expectations, expectation)
+	return expectation
+}
+
+// Then sets up ThingImageRepository.Delete return parameters for the expectation previously defined by the When method
+func (e *ThingImageRepositoryMockDeleteExpectation) Then(err error) *ThingImageRepositoryMock {
+	e.results = &ThingImageRepositoryMockDeleteResults{err}
+	return e.mock
+}
+
+// Times sets number of times ThingImageRepository.Delete should be invoked
+func (mmDelete *mThingImageRepositoryMockDelete) Times(n uint64) *mThingImageRepositoryMockDelete {
+	if n == 0 {
+		mmDelete.mock.t.Fatalf("Times of ThingImageRepositoryMock.Delete mock can not be zero")
+	}
+	mm_atomic.StoreUint64(&mmDelete.expectedInvocations, n)
+	return mmDelete
+}
+
+func (mmDelete *mThingImageRepositoryMockDelete) invocationsDone() bool {
+	if len(mmDelete.expectations) == 0 && mmDelete.defaultExpectation == nil && mmDelete.mock.funcDelete == nil {
+		return true
+	}
+
+	totalInvocations := mm_atomic.LoadUint64(&mmDelete.mock.afterDeleteCounter)
+	expectedInvocations := mm_atomic.LoadUint64(&mmDelete.expectedInvocations)
+
+	return totalInvocations > 0 && (expectedInvocations == 0 || expectedInvocations == totalInvocations)
+}
+
+// Delete implements place.ThingImageRepository
+func (mmDelete *ThingImageRepositoryMock) Delete(ctx context.Context, imageID int, tx *sql.Tx) (err error) {
+	mm_atomic.AddUint64(&mmDelete.beforeDeleteCounter, 1)
+	defer mm_atomic.AddUint64(&mmDelete.afterDeleteCounter, 1)
+
+	if mmDelete.inspectFuncDelete != nil {
+		mmDelete.inspectFuncDelete(ctx, imageID, tx)
+	}
+
+	mm_params := ThingImageRepositoryMockDeleteParams{ctx, imageID, tx}
+
+	// Record call args
+	mmDelete.DeleteMock.mutex.Lock()
+	mmDelete.DeleteMock.callArgs = append(mmDelete.DeleteMock.callArgs, &mm_params)
+	mmDelete.DeleteMock.mutex.Unlock()
+
+	for _, e := range mmDelete.DeleteMock.expectations {
+		if minimock.Equal(*e.params, mm_params) {
+			mm_atomic.AddUint64(&e.Counter, 1)
+			return e.results.err
+		}
+	}
+
+	if mmDelete.DeleteMock.defaultExpectation != nil {
+		mm_atomic.AddUint64(&mmDelete.DeleteMock.defaultExpectation.Counter, 1)
+		mm_want := mmDelete.DeleteMock.defaultExpectation.params
+		mm_want_ptrs := mmDelete.DeleteMock.defaultExpectation.paramPtrs
+
+		mm_got := ThingImageRepositoryMockDeleteParams{ctx, imageID, tx}
+
+		if mm_want_ptrs != nil {
+
+			if mm_want_ptrs.ctx != nil && !minimock.Equal(*mm_want_ptrs.ctx, mm_got.ctx) {
+				mmDelete.t.Errorf("ThingImageRepositoryMock.Delete got unexpected parameter ctx, want: %#v, got: %#v%s\n", *mm_want_ptrs.ctx, mm_got.ctx, minimock.Diff(*mm_want_ptrs.ctx, mm_got.ctx))
+			}
+
+			if mm_want_ptrs.imageID != nil && !minimock.Equal(*mm_want_ptrs.imageID, mm_got.imageID) {
+				mmDelete.t.Errorf("ThingImageRepositoryMock.Delete got unexpected parameter imageID, want: %#v, got: %#v%s\n", *mm_want_ptrs.imageID, mm_got.imageID, minimock.Diff(*mm_want_ptrs.imageID, mm_got.imageID))
+			}
+
+			if mm_want_ptrs.tx != nil && !minimock.Equal(*mm_want_ptrs.tx, mm_got.tx) {
+				mmDelete.t.Errorf("ThingImageRepositoryMock.Delete got unexpected parameter tx, want: %#v, got: %#v%s\n", *mm_want_ptrs.tx, mm_got.tx, minimock.Diff(*mm_want_ptrs.tx, mm_got.tx))
+			}
+
+		} else if mm_want != nil && !minimock.Equal(*mm_want, mm_got) {
+			mmDelete.t.Errorf("ThingImageRepositoryMock.Delete got unexpected parameters, want: %#v, got: %#v%s\n", *mm_want, mm_got, minimock.Diff(*mm_want, mm_got))
+		}
+
+		mm_results := mmDelete.DeleteMock.defaultExpectation.results
+		if mm_results == nil {
+			mmDelete.t.Fatal("No results are set for the ThingImageRepositoryMock.Delete")
+		}
+		return (*mm_results).err
+	}
+	if mmDelete.funcDelete != nil {
+		return mmDelete.funcDelete(ctx, imageID, tx)
+	}
+	mmDelete.t.Fatalf("Unexpected call to ThingImageRepositoryMock.Delete. %v %v %v", ctx, imageID, tx)
+	return
+}
+
+// DeleteAfterCounter returns a count of finished ThingImageRepositoryMock.Delete invocations
+func (mmDelete *ThingImageRepositoryMock) DeleteAfterCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmDelete.afterDeleteCounter)
+}
+
+// DeleteBeforeCounter returns a count of ThingImageRepositoryMock.Delete invocations
+func (mmDelete *ThingImageRepositoryMock) DeleteBeforeCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmDelete.beforeDeleteCounter)
+}
+
+// Calls returns a list of arguments used in each call to ThingImageRepositoryMock.Delete.
+// The list is in the same order as the calls were made (i.e. recent calls have a higher index)
+func (mmDelete *mThingImageRepositoryMockDelete) Calls() []*ThingImageRepositoryMockDeleteParams {
+	mmDelete.mutex.RLock()
+
+	argCopy := make([]*ThingImageRepositoryMockDeleteParams, len(mmDelete.callArgs))
+	copy(argCopy, mmDelete.callArgs)
+
+	mmDelete.mutex.RUnlock()
+
+	return argCopy
+}
+
+// MinimockDeleteDone returns true if the count of the Delete invocations corresponds
+// the number of defined expectations
+func (m *ThingImageRepositoryMock) MinimockDeleteDone() bool {
+	if m.DeleteMock.optional {
+		// Optional methods provide '0 or more' call count restriction.
+		return true
+	}
+
+	for _, e := range m.DeleteMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			return false
+		}
+	}
+
+	return m.DeleteMock.invocationsDone()
+}
+
+// MinimockDeleteInspect logs each unmet expectation
+func (m *ThingImageRepositoryMock) MinimockDeleteInspect() {
+	for _, e := range m.DeleteMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			m.t.Errorf("Expected call to ThingImageRepositoryMock.Delete with params: %#v", *e.params)
+		}
+	}
+
+	afterDeleteCounter := mm_atomic.LoadUint64(&m.afterDeleteCounter)
+	// if default expectation was set then invocations count should be greater than zero
+	if m.DeleteMock.defaultExpectation != nil && afterDeleteCounter < 1 {
+		if m.DeleteMock.defaultExpectation.params == nil {
+			m.t.Error("Expected call to ThingImageRepositoryMock.Delete")
+		} else {
+			m.t.Errorf("Expected call to ThingImageRepositoryMock.Delete with params: %#v", *m.DeleteMock.defaultExpectation.params)
+		}
+	}
+	// if func was set then invocations count should be greater than zero
+	if m.funcDelete != nil && afterDeleteCounter < 1 {
+		m.t.Error("Expected call to ThingImageRepositoryMock.Delete")
+	}
+
+	if !m.DeleteMock.invocationsDone() && afterDeleteCounter > 0 {
+		m.t.Errorf("Expected %d calls to ThingImageRepositoryMock.Delete but found %d calls",
+			mm_atomic.LoadUint64(&m.DeleteMock.expectedInvocations), afterDeleteCounter)
+	}
+}
+
+type mThingImageRepositoryMockGetByThingID struct {
+	optional           bool
+	mock               *ThingImageRepositoryMock
+	defaultExpectation *ThingImageRepositoryMockGetByThingIDExpectation
+	expectations       []*ThingImageRepositoryMockGetByThingIDExpectation
+
+	callArgs []*ThingImageRepositoryMockGetByThingIDParams
+	mutex    sync.RWMutex
+
+	expectedInvocations uint64
+}
+
+// ThingImageRepositoryMockGetByThingIDExpectation specifies expectation struct of the ThingImageRepository.GetByThingID
+type ThingImageRepositoryMockGetByThingIDExpectation struct {
+	mock      *ThingImageRepositoryMock
+	params    *ThingImageRepositoryMockGetByThingIDParams
+	paramPtrs *ThingImageRepositoryMockGetByThingIDParamPtrs
+	results   *ThingImageRepositoryMockGetByThingIDResults
+	Counter   uint64
+}
+
+// ThingImageRepositoryMockGetByThingIDParams contains parameters of the ThingImageRepository.GetByThingID
+type ThingImageRepositoryMockGetByThingIDParams struct {
+	ctx     context.Context
+	thingID int
+}
+
+// ThingImageRepositoryMockGetByThingIDParamPtrs contains pointers to parameters of the ThingImageRepository.GetByThingID
+type ThingImageRepositoryMockGetByThingIDParamPtrs struct {
+	ctx     *context.Context
+	thingID *int
+}
+
+// ThingImageRepositoryMockGetByThingIDResults contains results of the ThingImageRepository.GetByThingID
+type ThingImageRepositoryMockGetByThingIDResults struct {
+	ia1 []models.Image
+	err error
+}
+
+// Marks this method to be optional. The default behavior of any method with Return() is '1 or more', meaning
+// the test will fail minimock's automatic final call check if the mocked method was not called at least once.
+// Optional() makes method check to work in '0 or more' mode.
+// It is NOT RECOMMENDED to use this option unless you really need it, as default behaviour helps to
+// catch the problems when the expected method call is totally skipped during test run.
+func (mmGetByThingID *mThingImageRepositoryMockGetByThingID) Optional() *mThingImageRepositoryMockGetByThingID {
+	mmGetByThingID.optional = true
+	return mmGetByThingID
+}
+
+// Expect sets up expected params for ThingImageRepository.GetByThingID
+func (mmGetByThingID *mThingImageRepositoryMockGetByThingID) Expect(ctx context.Context, thingID int) *mThingImageRepositoryMockGetByThingID {
+	if mmGetByThingID.mock.funcGetByThingID != nil {
+		mmGetByThingID.mock.t.Fatalf("ThingImageRepositoryMock.GetByThingID mock is already set by Set")
+	}
+
+	if mmGetByThingID.defaultExpectation == nil {
+		mmGetByThingID.defaultExpectation = &ThingImageRepositoryMockGetByThingIDExpectation{}
+	}
+
+	if mmGetByThingID.defaultExpectation.paramPtrs != nil {
+		mmGetByThingID.mock.t.Fatalf("ThingImageRepositoryMock.GetByThingID mock is already set by ExpectParams functions")
+	}
+
+	mmGetByThingID.defaultExpectation.params = &ThingImageRepositoryMockGetByThingIDParams{ctx, thingID}
+	for _, e := range mmGetByThingID.expectations {
+		if minimock.Equal(e.params, mmGetByThingID.defaultExpectation.params) {
+			mmGetByThingID.mock.t.Fatalf("Expectation set by When has same params: %#v", *mmGetByThingID.defaultExpectation.params)
+		}
+	}
+
+	return mmGetByThingID
+}
+
+// ExpectCtxParam1 sets up expected param ctx for ThingImageRepository.GetByThingID
+func (mmGetByThingID *mThingImageRepositoryMockGetByThingID) ExpectCtxParam1(ctx context.Context) *mThingImageRepositoryMockGetByThingID {
+	if mmGetByThingID.mock.funcGetByThingID != nil {
+		mmGetByThingID.mock.t.Fatalf("ThingImageRepositoryMock.GetByThingID mock is already set by Set")
+	}
+
+	if mmGetByThingID.defaultExpectation == nil {
+		mmGetByThingID.defaultExpectation = &ThingImageRepositoryMockGetByThingIDExpectation{}
+	}
+
+	if mmGetByThingID.defaultExpectation.params != nil {
+		mmGetByThingID.mock.t.Fatalf("ThingImageRepositoryMock.GetByThingID mock is already set by Expect")
+	}
+
+	if mmGetByThingID.defaultExpectation.paramPtrs == nil {
+		mmGetByThingID.defaultExpectation.paramPtrs = &ThingImageRepositoryMockGetByThingIDParamPtrs{}
+	}
+	mmGetByThingID.defaultExpectation.paramPtrs.ctx = &ctx
+
+	return mmGetByThingID
+}
+
+// ExpectThingIDParam2 sets up expected param thingID for ThingImageRepository.GetByThingID
+func (mmGetByThingID *mThingImageRepositoryMockGetByThingID) ExpectThingIDParam2(thingID int) *mThingImageRepositoryMockGetByThingID {
+	if mmGetByThingID.mock.funcGetByThingID != nil {
+		mmGetByThingID.mock.t.Fatalf("ThingImageRepositoryMock.GetByThingID mock is already set by Set")
+	}
+
+	if mmGetByThingID.defaultExpectation == nil {
+		mmGetByThingID.defaultExpectation = &ThingImageRepositoryMockGetByThingIDExpectation{}
+	}
+
+	if mmGetByThingID.defaultExpectation.params != nil {
+		mmGetByThingID.mock.t.Fatalf("ThingImageRepositoryMock.GetByThingID mock is already set by Expect")
+	}
+
+	if mmGetByThingID.defaultExpectation.paramPtrs == nil {
+		mmGetByThingID.defaultExpectation.paramPtrs = &ThingImageRepositoryMockGetByThingIDParamPtrs{}
+	}
+	mmGetByThingID.defaultExpectation.paramPtrs.thingID = &thingID
+
+	return mmGetByThingID
+}
+
+// Inspect accepts an inspector function that has same arguments as the ThingImageRepository.GetByThingID
+func (mmGetByThingID *mThingImageRepositoryMockGetByThingID) Inspect(f func(ctx context.Context, thingID int)) *mThingImageRepositoryMockGetByThingID {
+	if mmGetByThingID.mock.inspectFuncGetByThingID != nil {
+		mmGetByThingID.mock.t.Fatalf("Inspect function is already set for ThingImageRepositoryMock.GetByThingID")
+	}
+
+	mmGetByThingID.mock.inspectFuncGetByThingID = f
+
+	return mmGetByThingID
+}
+
+// Return sets up results that will be returned by ThingImageRepository.GetByThingID
+func (mmGetByThingID *mThingImageRepositoryMockGetByThingID) Return(ia1 []models.Image, err error) *ThingImageRepositoryMock {
+	if mmGetByThingID.mock.funcGetByThingID != nil {
+		mmGetByThingID.mock.t.Fatalf("ThingImageRepositoryMock.GetByThingID mock is already set by Set")
+	}
+
+	if mmGetByThingID.defaultExpectation == nil {
+		mmGetByThingID.defaultExpectation = &ThingImageRepositoryMockGetByThingIDExpectation{mock: mmGetByThingID.mock}
+	}
+	mmGetByThingID.defaultExpectation.results = &ThingImageRepositoryMockGetByThingIDResults{ia1, err}
+	return mmGetByThingID.mock
+}
+
+// Set uses given function f to mock the ThingImageRepository.GetByThingID method
+func (mmGetByThingID *mThingImageRepositoryMockGetByThingID) Set(f func(ctx context.Context, thingID int) (ia1 []models.Image, err error)) *ThingImageRepositoryMock {
+	if mmGetByThingID.defaultExpectation != nil {
+		mmGetByThingID.mock.t.Fatalf("Default expectation is already set for the ThingImageRepository.GetByThingID method")
+	}
+
+	if len(mmGetByThingID.expectations) > 0 {
+		mmGetByThingID.mock.t.Fatalf("Some expectations are already set for the ThingImageRepository.GetByThingID method")
+	}
+
+	mmGetByThingID.mock.funcGetByThingID = f
+	return mmGetByThingID.mock
+}
+
+// When sets expectation for the ThingImageRepository.GetByThingID which will trigger the result defined by the following
+// Then helper
+func (mmGetByThingID *mThingImageRepositoryMockGetByThingID) When(ctx context.Context, thingID int) *ThingImageRepositoryMockGetByThingIDExpectation {
+	if mmGetByThingID.mock.funcGetByThingID != nil {
+		mmGetByThingID.mock.t.Fatalf("ThingImageRepositoryMock.GetByThingID mock is already set by Set")
+	}
+
+	expectation := &ThingImageRepositoryMockGetByThingIDExpectation{
+		mock:   mmGetByThingID.mock,
+		params: &ThingImageRepositoryMockGetByThingIDParams{ctx, thingID},
+	}
+	mmGetByThingID.expectations = append(mmGetByThingID.expectations, expectation)
+	return expectation
+}
+
+// Then sets up ThingImageRepository.GetByThingID return parameters for the expectation previously defined by the When method
+func (e *ThingImageRepositoryMockGetByThingIDExpectation) Then(ia1 []models.Image, err error) *ThingImageRepositoryMock {
+	e.results = &ThingImageRepositoryMockGetByThingIDResults{ia1, err}
+	return e.mock
+}
+
+// Times sets number of times ThingImageRepository.GetByThingID should be invoked
+func (mmGetByThingID *mThingImageRepositoryMockGetByThingID) Times(n uint64) *mThingImageRepositoryMockGetByThingID {
+	if n == 0 {
+		mmGetByThingID.mock.t.Fatalf("Times of ThingImageRepositoryMock.GetByThingID mock can not be zero")
+	}
+	mm_atomic.StoreUint64(&mmGetByThingID.expectedInvocations, n)
+	return mmGetByThingID
+}
+
+func (mmGetByThingID *mThingImageRepositoryMockGetByThingID) invocationsDone() bool {
+	if len(mmGetByThingID.expectations) == 0 && mmGetByThingID.defaultExpectation == nil && mmGetByThingID.mock.funcGetByThingID == nil {
+		return true
+	}
+
+	totalInvocations := mm_atomic.LoadUint64(&mmGetByThingID.mock.afterGetByThingIDCounter)
+	expectedInvocations := mm_atomic.LoadUint64(&mmGetByThingID.expectedInvocations)
+
+	return totalInvocations > 0 && (expectedInvocations == 0 || expectedInvocations == totalInvocations)
+}
+
+// GetByThingID implements place.ThingImageRepository
+func (mmGetByThingID *ThingImageRepositoryMock) GetByThingID(ctx context.Context, thingID int) (ia1 []models.Image, err error) {
+	mm_atomic.AddUint64(&mmGetByThingID.beforeGetByThingIDCounter, 1)
+	defer mm_atomic.AddUint64(&mmGetByThingID.afterGetByThingIDCounter, 1)
+
+	if mmGetByThingID.inspectFuncGetByThingID != nil {
+		mmGetByThingID.inspectFuncGetByThingID(ctx, thingID)
+	}
+
+	mm_params := ThingImageRepositoryMockGetByThingIDParams{ctx, thingID}
+
+	// Record call args
+	mmGetByThingID.GetByThingIDMock.mutex.Lock()
+	mmGetByThingID.GetByThingIDMock.callArgs = append(mmGetByThingID.GetByThingIDMock.callArgs, &mm_params)
+	mmGetByThingID.GetByThingIDMock.mutex.Unlock()
+
+	for _, e := range mmGetByThingID.GetByThingIDMock.expectations {
+		if minimock.Equal(*e.params, mm_params) {
+			mm_atomic.AddUint64(&e.Counter, 1)
+			return e.results.ia1, e.results.err
+		}
+	}
+
+	if mmGetByThingID.GetByThingIDMock.defaultExpectation != nil {
+		mm_atomic.AddUint64(&mmGetByThingID.GetByThingIDMock.defaultExpectation.Counter, 1)
+		mm_want := mmGetByThingID.GetByThingIDMock.defaultExpectation.params
+		mm_want_ptrs := mmGetByThingID.GetByThingIDMock.defaultExpectation.paramPtrs
+
+		mm_got := ThingImageRepositoryMockGetByThingIDParams{ctx, thingID}
+
+		if mm_want_ptrs != nil {
+
+			if mm_want_ptrs.ctx != nil && !minimock.Equal(*mm_want_ptrs.ctx, mm_got.ctx) {
+				mmGetByThingID.t.Errorf("ThingImageRepositoryMock.GetByThingID got unexpected parameter ctx, want: %#v, got: %#v%s\n", *mm_want_ptrs.ctx, mm_got.ctx, minimock.Diff(*mm_want_ptrs.ctx, mm_got.ctx))
+			}
+
+			if mm_want_ptrs.thingID != nil && !minimock.Equal(*mm_want_ptrs.thingID, mm_got.thingID) {
+				mmGetByThingID.t.Errorf("ThingImageRepositoryMock.GetByThingID got unexpected parameter thingID, want: %#v, got: %#v%s\n", *mm_want_ptrs.thingID, mm_got.thingID, minimock.Diff(*mm_want_ptrs.thingID, mm_got.thingID))
+			}
+
+		} else if mm_want != nil && !minimock.Equal(*mm_want, mm_got) {
+			mmGetByThingID.t.Errorf("ThingImageRepositoryMock.GetByThingID got unexpected parameters, want: %#v, got: %#v%s\n", *mm_want, mm_got, minimock.Diff(*mm_want, mm_got))
+		}
+
+		mm_results := mmGetByThingID.GetByThingIDMock.defaultExpectation.results
+		if mm_results == nil {
+			mmGetByThingID.t.Fatal("No results are set for the ThingImageRepositoryMock.GetByThingID")
+		}
+		return (*mm_results).ia1, (*mm_results).err
+	}
+	if mmGetByThingID.funcGetByThingID != nil {
+		return mmGetByThingID.funcGetByThingID(ctx, thingID)
+	}
+	mmGetByThingID.t.Fatalf("Unexpected call to ThingImageRepositoryMock.GetByThingID. %v %v", ctx, thingID)
+	return
+}
+
+// GetByThingIDAfterCounter returns a count of finished ThingImageRepositoryMock.GetByThingID invocations
+func (mmGetByThingID *ThingImageRepositoryMock) GetByThingIDAfterCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmGetByThingID.afterGetByThingIDCounter)
+}
+
+// GetByThingIDBeforeCounter returns a count of ThingImageRepositoryMock.GetByThingID invocations
+func (mmGetByThingID *ThingImageRepositoryMock) GetByThingIDBeforeCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmGetByThingID.beforeGetByThingIDCounter)
+}
+
+// Calls returns a list of arguments used in each call to ThingImageRepositoryMock.GetByThingID.
+// The list is in the same order as the calls were made (i.e. recent calls have a higher index)
+func (mmGetByThingID *mThingImageRepositoryMockGetByThingID) Calls() []*ThingImageRepositoryMockGetByThingIDParams {
+	mmGetByThingID.mutex.RLock()
+
+	argCopy := make([]*ThingImageRepositoryMockGetByThingIDParams, len(mmGetByThingID.callArgs))
+	copy(argCopy, mmGetByThingID.callArgs)
+
+	mmGetByThingID.mutex.RUnlock()
+
+	return argCopy
+}
+
+// MinimockGetByThingIDDone returns true if the count of the GetByThingID invocations corresponds
+// the number of defined expectations
+func (m *ThingImageRepositoryMock) MinimockGetByThingIDDone() bool {
+	if m.GetByThingIDMock.optional {
+		// Optional methods provide '0 or more' call count restriction.
+		return true
+	}
+
+	for _, e := range m.GetByThingIDMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			return false
+		}
+	}
+
+	return m.GetByThingIDMock.invocationsDone()
+}
+
+// MinimockGetByThingIDInspect logs each unmet expectation
+func (m *ThingImageRepositoryMock) MinimockGetByThingIDInspect() {
+	for _, e := range m.GetByThingIDMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			m.t.Errorf("Expected call to ThingImageRepositoryMock.GetByThingID with params: %#v", *e.params)
+		}
+	}
+
+	afterGetByThingIDCounter := mm_atomic.LoadUint64(&m.afterGetByThingIDCounter)
+	// if default expectation was set then invocations count should be greater than zero
+	if m.GetByThingIDMock.defaultExpectation != nil && afterGetByThingIDCounter < 1 {
+		if m.GetByThingIDMock.defaultExpectation.params == nil {
+			m.t.Error("Expected call to ThingImageRepositoryMock.GetByThingID")
+		} else {
+			m.t.Errorf("Expected call to ThingImageRepositoryMock.GetByThingID with params: %#v", *m.GetByThingIDMock.defaultExpectation.params)
+		}
+	}
+	// if func was set then invocations count should be greater than zero
+	if m.funcGetByThingID != nil && afterGetByThingIDCounter < 1 {
+		m.t.Error("Expected call to ThingImageRepositoryMock.GetByThingID")
+	}
+
+	if !m.GetByThingIDMock.invocationsDone() && afterGetByThingIDCounter > 0 {
+		m.t.Errorf("Expected %d calls to ThingImageRepositoryMock.GetByThingID but found %d calls",
+			mm_atomic.LoadUint64(&m.GetByThingIDMock.expectedInvocations), afterGetByThingIDCounter)
+	}
+}
+
+// MinimockFinish checks that all mocked methods have been called the expected number of times
+func (m *ThingImageRepositoryMock) MinimockFinish() {
+	m.finishOnce.Do(func() {
+		if !m.minimockDone() {
+			m.MinimockDeleteInspect()
+
+			m.MinimockGetByThingIDInspect()
+		}
+	})
+}
+
+// MinimockWait waits for all mocked methods to be called the expected number of times
+func (m *ThingImageRepositoryMock) MinimockWait(timeout mm_time.Duration) {
+	timeoutCh := mm_time.After(timeout)
+	for {
+		if m.minimockDone() {
+			return
+		}
+		select {
+		case <-timeoutCh:
+			m.MinimockFinish()
+			return
+		case <-mm_time.After(10 * mm_time.Millisecond):
+		}
+	}
+}
+
+func (m *ThingImageRepositoryMock) minimockDone() bool {
+	done := true
+	return done &&
+		m.MinimockDeleteDone() &&
+		m.MinimockGetByThingIDDone()
+}

+ 422 - 0
internal/api/v1/place/mocks/thing_notification_repository_minimock.go

@@ -0,0 +1,422 @@
+// Code generated by http://github.com/gojuno/minimock (v3.3.13). DO NOT EDIT.
+
+package mocks
+
+//go:generate minimock -i git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/place.ThingNotificationRepository -o thing_notification_repository_minimock.go -n ThingNotificationRepositoryMock -p mocks
+
+import (
+	"context"
+	"database/sql"
+	"sync"
+	mm_atomic "sync/atomic"
+	mm_time "time"
+
+	"github.com/gojuno/minimock/v3"
+)
+
+// ThingNotificationRepositoryMock implements place.ThingNotificationRepository
+type ThingNotificationRepositoryMock struct {
+	t          minimock.Tester
+	finishOnce sync.Once
+
+	funcDelete          func(ctx context.Context, thingID int, tx *sql.Tx) (err error)
+	inspectFuncDelete   func(ctx context.Context, thingID int, tx *sql.Tx)
+	afterDeleteCounter  uint64
+	beforeDeleteCounter uint64
+	DeleteMock          mThingNotificationRepositoryMockDelete
+}
+
+// NewThingNotificationRepositoryMock returns a mock for place.ThingNotificationRepository
+func NewThingNotificationRepositoryMock(t minimock.Tester) *ThingNotificationRepositoryMock {
+	m := &ThingNotificationRepositoryMock{t: t}
+
+	if controller, ok := t.(minimock.MockController); ok {
+		controller.RegisterMocker(m)
+	}
+
+	m.DeleteMock = mThingNotificationRepositoryMockDelete{mock: m}
+	m.DeleteMock.callArgs = []*ThingNotificationRepositoryMockDeleteParams{}
+
+	t.Cleanup(m.MinimockFinish)
+
+	return m
+}
+
+type mThingNotificationRepositoryMockDelete struct {
+	optional           bool
+	mock               *ThingNotificationRepositoryMock
+	defaultExpectation *ThingNotificationRepositoryMockDeleteExpectation
+	expectations       []*ThingNotificationRepositoryMockDeleteExpectation
+
+	callArgs []*ThingNotificationRepositoryMockDeleteParams
+	mutex    sync.RWMutex
+
+	expectedInvocations uint64
+}
+
+// ThingNotificationRepositoryMockDeleteExpectation specifies expectation struct of the ThingNotificationRepository.Delete
+type ThingNotificationRepositoryMockDeleteExpectation struct {
+	mock      *ThingNotificationRepositoryMock
+	params    *ThingNotificationRepositoryMockDeleteParams
+	paramPtrs *ThingNotificationRepositoryMockDeleteParamPtrs
+	results   *ThingNotificationRepositoryMockDeleteResults
+	Counter   uint64
+}
+
+// ThingNotificationRepositoryMockDeleteParams contains parameters of the ThingNotificationRepository.Delete
+type ThingNotificationRepositoryMockDeleteParams struct {
+	ctx     context.Context
+	thingID int
+	tx      *sql.Tx
+}
+
+// ThingNotificationRepositoryMockDeleteParamPtrs contains pointers to parameters of the ThingNotificationRepository.Delete
+type ThingNotificationRepositoryMockDeleteParamPtrs struct {
+	ctx     *context.Context
+	thingID *int
+	tx      **sql.Tx
+}
+
+// ThingNotificationRepositoryMockDeleteResults contains results of the ThingNotificationRepository.Delete
+type ThingNotificationRepositoryMockDeleteResults struct {
+	err error
+}
+
+// Marks this method to be optional. The default behavior of any method with Return() is '1 or more', meaning
+// the test will fail minimock's automatic final call check if the mocked method was not called at least once.
+// Optional() makes method check to work in '0 or more' mode.
+// It is NOT RECOMMENDED to use this option unless you really need it, as default behaviour helps to
+// catch the problems when the expected method call is totally skipped during test run.
+func (mmDelete *mThingNotificationRepositoryMockDelete) Optional() *mThingNotificationRepositoryMockDelete {
+	mmDelete.optional = true
+	return mmDelete
+}
+
+// Expect sets up expected params for ThingNotificationRepository.Delete
+func (mmDelete *mThingNotificationRepositoryMockDelete) Expect(ctx context.Context, thingID int, tx *sql.Tx) *mThingNotificationRepositoryMockDelete {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("ThingNotificationRepositoryMock.Delete mock is already set by Set")
+	}
+
+	if mmDelete.defaultExpectation == nil {
+		mmDelete.defaultExpectation = &ThingNotificationRepositoryMockDeleteExpectation{}
+	}
+
+	if mmDelete.defaultExpectation.paramPtrs != nil {
+		mmDelete.mock.t.Fatalf("ThingNotificationRepositoryMock.Delete mock is already set by ExpectParams functions")
+	}
+
+	mmDelete.defaultExpectation.params = &ThingNotificationRepositoryMockDeleteParams{ctx, thingID, tx}
+	for _, e := range mmDelete.expectations {
+		if minimock.Equal(e.params, mmDelete.defaultExpectation.params) {
+			mmDelete.mock.t.Fatalf("Expectation set by When has same params: %#v", *mmDelete.defaultExpectation.params)
+		}
+	}
+
+	return mmDelete
+}
+
+// ExpectCtxParam1 sets up expected param ctx for ThingNotificationRepository.Delete
+func (mmDelete *mThingNotificationRepositoryMockDelete) ExpectCtxParam1(ctx context.Context) *mThingNotificationRepositoryMockDelete {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("ThingNotificationRepositoryMock.Delete mock is already set by Set")
+	}
+
+	if mmDelete.defaultExpectation == nil {
+		mmDelete.defaultExpectation = &ThingNotificationRepositoryMockDeleteExpectation{}
+	}
+
+	if mmDelete.defaultExpectation.params != nil {
+		mmDelete.mock.t.Fatalf("ThingNotificationRepositoryMock.Delete mock is already set by Expect")
+	}
+
+	if mmDelete.defaultExpectation.paramPtrs == nil {
+		mmDelete.defaultExpectation.paramPtrs = &ThingNotificationRepositoryMockDeleteParamPtrs{}
+	}
+	mmDelete.defaultExpectation.paramPtrs.ctx = &ctx
+
+	return mmDelete
+}
+
+// ExpectThingIDParam2 sets up expected param thingID for ThingNotificationRepository.Delete
+func (mmDelete *mThingNotificationRepositoryMockDelete) ExpectThingIDParam2(thingID int) *mThingNotificationRepositoryMockDelete {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("ThingNotificationRepositoryMock.Delete mock is already set by Set")
+	}
+
+	if mmDelete.defaultExpectation == nil {
+		mmDelete.defaultExpectation = &ThingNotificationRepositoryMockDeleteExpectation{}
+	}
+
+	if mmDelete.defaultExpectation.params != nil {
+		mmDelete.mock.t.Fatalf("ThingNotificationRepositoryMock.Delete mock is already set by Expect")
+	}
+
+	if mmDelete.defaultExpectation.paramPtrs == nil {
+		mmDelete.defaultExpectation.paramPtrs = &ThingNotificationRepositoryMockDeleteParamPtrs{}
+	}
+	mmDelete.defaultExpectation.paramPtrs.thingID = &thingID
+
+	return mmDelete
+}
+
+// ExpectTxParam3 sets up expected param tx for ThingNotificationRepository.Delete
+func (mmDelete *mThingNotificationRepositoryMockDelete) ExpectTxParam3(tx *sql.Tx) *mThingNotificationRepositoryMockDelete {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("ThingNotificationRepositoryMock.Delete mock is already set by Set")
+	}
+
+	if mmDelete.defaultExpectation == nil {
+		mmDelete.defaultExpectation = &ThingNotificationRepositoryMockDeleteExpectation{}
+	}
+
+	if mmDelete.defaultExpectation.params != nil {
+		mmDelete.mock.t.Fatalf("ThingNotificationRepositoryMock.Delete mock is already set by Expect")
+	}
+
+	if mmDelete.defaultExpectation.paramPtrs == nil {
+		mmDelete.defaultExpectation.paramPtrs = &ThingNotificationRepositoryMockDeleteParamPtrs{}
+	}
+	mmDelete.defaultExpectation.paramPtrs.tx = &tx
+
+	return mmDelete
+}
+
+// Inspect accepts an inspector function that has same arguments as the ThingNotificationRepository.Delete
+func (mmDelete *mThingNotificationRepositoryMockDelete) Inspect(f func(ctx context.Context, thingID int, tx *sql.Tx)) *mThingNotificationRepositoryMockDelete {
+	if mmDelete.mock.inspectFuncDelete != nil {
+		mmDelete.mock.t.Fatalf("Inspect function is already set for ThingNotificationRepositoryMock.Delete")
+	}
+
+	mmDelete.mock.inspectFuncDelete = f
+
+	return mmDelete
+}
+
+// Return sets up results that will be returned by ThingNotificationRepository.Delete
+func (mmDelete *mThingNotificationRepositoryMockDelete) Return(err error) *ThingNotificationRepositoryMock {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("ThingNotificationRepositoryMock.Delete mock is already set by Set")
+	}
+
+	if mmDelete.defaultExpectation == nil {
+		mmDelete.defaultExpectation = &ThingNotificationRepositoryMockDeleteExpectation{mock: mmDelete.mock}
+	}
+	mmDelete.defaultExpectation.results = &ThingNotificationRepositoryMockDeleteResults{err}
+	return mmDelete.mock
+}
+
+// Set uses given function f to mock the ThingNotificationRepository.Delete method
+func (mmDelete *mThingNotificationRepositoryMockDelete) Set(f func(ctx context.Context, thingID int, tx *sql.Tx) (err error)) *ThingNotificationRepositoryMock {
+	if mmDelete.defaultExpectation != nil {
+		mmDelete.mock.t.Fatalf("Default expectation is already set for the ThingNotificationRepository.Delete method")
+	}
+
+	if len(mmDelete.expectations) > 0 {
+		mmDelete.mock.t.Fatalf("Some expectations are already set for the ThingNotificationRepository.Delete method")
+	}
+
+	mmDelete.mock.funcDelete = f
+	return mmDelete.mock
+}
+
+// When sets expectation for the ThingNotificationRepository.Delete which will trigger the result defined by the following
+// Then helper
+func (mmDelete *mThingNotificationRepositoryMockDelete) When(ctx context.Context, thingID int, tx *sql.Tx) *ThingNotificationRepositoryMockDeleteExpectation {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("ThingNotificationRepositoryMock.Delete mock is already set by Set")
+	}
+
+	expectation := &ThingNotificationRepositoryMockDeleteExpectation{
+		mock:   mmDelete.mock,
+		params: &ThingNotificationRepositoryMockDeleteParams{ctx, thingID, tx},
+	}
+	mmDelete.expectations = append(mmDelete.expectations, expectation)
+	return expectation
+}
+
+// Then sets up ThingNotificationRepository.Delete return parameters for the expectation previously defined by the When method
+func (e *ThingNotificationRepositoryMockDeleteExpectation) Then(err error) *ThingNotificationRepositoryMock {
+	e.results = &ThingNotificationRepositoryMockDeleteResults{err}
+	return e.mock
+}
+
+// Times sets number of times ThingNotificationRepository.Delete should be invoked
+func (mmDelete *mThingNotificationRepositoryMockDelete) Times(n uint64) *mThingNotificationRepositoryMockDelete {
+	if n == 0 {
+		mmDelete.mock.t.Fatalf("Times of ThingNotificationRepositoryMock.Delete mock can not be zero")
+	}
+	mm_atomic.StoreUint64(&mmDelete.expectedInvocations, n)
+	return mmDelete
+}
+
+func (mmDelete *mThingNotificationRepositoryMockDelete) invocationsDone() bool {
+	if len(mmDelete.expectations) == 0 && mmDelete.defaultExpectation == nil && mmDelete.mock.funcDelete == nil {
+		return true
+	}
+
+	totalInvocations := mm_atomic.LoadUint64(&mmDelete.mock.afterDeleteCounter)
+	expectedInvocations := mm_atomic.LoadUint64(&mmDelete.expectedInvocations)
+
+	return totalInvocations > 0 && (expectedInvocations == 0 || expectedInvocations == totalInvocations)
+}
+
+// Delete implements place.ThingNotificationRepository
+func (mmDelete *ThingNotificationRepositoryMock) Delete(ctx context.Context, thingID int, tx *sql.Tx) (err error) {
+	mm_atomic.AddUint64(&mmDelete.beforeDeleteCounter, 1)
+	defer mm_atomic.AddUint64(&mmDelete.afterDeleteCounter, 1)
+
+	if mmDelete.inspectFuncDelete != nil {
+		mmDelete.inspectFuncDelete(ctx, thingID, tx)
+	}
+
+	mm_params := ThingNotificationRepositoryMockDeleteParams{ctx, thingID, tx}
+
+	// Record call args
+	mmDelete.DeleteMock.mutex.Lock()
+	mmDelete.DeleteMock.callArgs = append(mmDelete.DeleteMock.callArgs, &mm_params)
+	mmDelete.DeleteMock.mutex.Unlock()
+
+	for _, e := range mmDelete.DeleteMock.expectations {
+		if minimock.Equal(*e.params, mm_params) {
+			mm_atomic.AddUint64(&e.Counter, 1)
+			return e.results.err
+		}
+	}
+
+	if mmDelete.DeleteMock.defaultExpectation != nil {
+		mm_atomic.AddUint64(&mmDelete.DeleteMock.defaultExpectation.Counter, 1)
+		mm_want := mmDelete.DeleteMock.defaultExpectation.params
+		mm_want_ptrs := mmDelete.DeleteMock.defaultExpectation.paramPtrs
+
+		mm_got := ThingNotificationRepositoryMockDeleteParams{ctx, thingID, tx}
+
+		if mm_want_ptrs != nil {
+
+			if mm_want_ptrs.ctx != nil && !minimock.Equal(*mm_want_ptrs.ctx, mm_got.ctx) {
+				mmDelete.t.Errorf("ThingNotificationRepositoryMock.Delete got unexpected parameter ctx, want: %#v, got: %#v%s\n", *mm_want_ptrs.ctx, mm_got.ctx, minimock.Diff(*mm_want_ptrs.ctx, mm_got.ctx))
+			}
+
+			if mm_want_ptrs.thingID != nil && !minimock.Equal(*mm_want_ptrs.thingID, mm_got.thingID) {
+				mmDelete.t.Errorf("ThingNotificationRepositoryMock.Delete got unexpected parameter thingID, want: %#v, got: %#v%s\n", *mm_want_ptrs.thingID, mm_got.thingID, minimock.Diff(*mm_want_ptrs.thingID, mm_got.thingID))
+			}
+
+			if mm_want_ptrs.tx != nil && !minimock.Equal(*mm_want_ptrs.tx, mm_got.tx) {
+				mmDelete.t.Errorf("ThingNotificationRepositoryMock.Delete got unexpected parameter tx, want: %#v, got: %#v%s\n", *mm_want_ptrs.tx, mm_got.tx, minimock.Diff(*mm_want_ptrs.tx, mm_got.tx))
+			}
+
+		} else if mm_want != nil && !minimock.Equal(*mm_want, mm_got) {
+			mmDelete.t.Errorf("ThingNotificationRepositoryMock.Delete got unexpected parameters, want: %#v, got: %#v%s\n", *mm_want, mm_got, minimock.Diff(*mm_want, mm_got))
+		}
+
+		mm_results := mmDelete.DeleteMock.defaultExpectation.results
+		if mm_results == nil {
+			mmDelete.t.Fatal("No results are set for the ThingNotificationRepositoryMock.Delete")
+		}
+		return (*mm_results).err
+	}
+	if mmDelete.funcDelete != nil {
+		return mmDelete.funcDelete(ctx, thingID, tx)
+	}
+	mmDelete.t.Fatalf("Unexpected call to ThingNotificationRepositoryMock.Delete. %v %v %v", ctx, thingID, tx)
+	return
+}
+
+// DeleteAfterCounter returns a count of finished ThingNotificationRepositoryMock.Delete invocations
+func (mmDelete *ThingNotificationRepositoryMock) DeleteAfterCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmDelete.afterDeleteCounter)
+}
+
+// DeleteBeforeCounter returns a count of ThingNotificationRepositoryMock.Delete invocations
+func (mmDelete *ThingNotificationRepositoryMock) DeleteBeforeCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmDelete.beforeDeleteCounter)
+}
+
+// Calls returns a list of arguments used in each call to ThingNotificationRepositoryMock.Delete.
+// The list is in the same order as the calls were made (i.e. recent calls have a higher index)
+func (mmDelete *mThingNotificationRepositoryMockDelete) Calls() []*ThingNotificationRepositoryMockDeleteParams {
+	mmDelete.mutex.RLock()
+
+	argCopy := make([]*ThingNotificationRepositoryMockDeleteParams, len(mmDelete.callArgs))
+	copy(argCopy, mmDelete.callArgs)
+
+	mmDelete.mutex.RUnlock()
+
+	return argCopy
+}
+
+// MinimockDeleteDone returns true if the count of the Delete invocations corresponds
+// the number of defined expectations
+func (m *ThingNotificationRepositoryMock) MinimockDeleteDone() bool {
+	if m.DeleteMock.optional {
+		// Optional methods provide '0 or more' call count restriction.
+		return true
+	}
+
+	for _, e := range m.DeleteMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			return false
+		}
+	}
+
+	return m.DeleteMock.invocationsDone()
+}
+
+// MinimockDeleteInspect logs each unmet expectation
+func (m *ThingNotificationRepositoryMock) MinimockDeleteInspect() {
+	for _, e := range m.DeleteMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			m.t.Errorf("Expected call to ThingNotificationRepositoryMock.Delete with params: %#v", *e.params)
+		}
+	}
+
+	afterDeleteCounter := mm_atomic.LoadUint64(&m.afterDeleteCounter)
+	// if default expectation was set then invocations count should be greater than zero
+	if m.DeleteMock.defaultExpectation != nil && afterDeleteCounter < 1 {
+		if m.DeleteMock.defaultExpectation.params == nil {
+			m.t.Error("Expected call to ThingNotificationRepositoryMock.Delete")
+		} else {
+			m.t.Errorf("Expected call to ThingNotificationRepositoryMock.Delete with params: %#v", *m.DeleteMock.defaultExpectation.params)
+		}
+	}
+	// if func was set then invocations count should be greater than zero
+	if m.funcDelete != nil && afterDeleteCounter < 1 {
+		m.t.Error("Expected call to ThingNotificationRepositoryMock.Delete")
+	}
+
+	if !m.DeleteMock.invocationsDone() && afterDeleteCounter > 0 {
+		m.t.Errorf("Expected %d calls to ThingNotificationRepositoryMock.Delete but found %d calls",
+			mm_atomic.LoadUint64(&m.DeleteMock.expectedInvocations), afterDeleteCounter)
+	}
+}
+
+// MinimockFinish checks that all mocked methods have been called the expected number of times
+func (m *ThingNotificationRepositoryMock) MinimockFinish() {
+	m.finishOnce.Do(func() {
+		if !m.minimockDone() {
+			m.MinimockDeleteInspect()
+		}
+	})
+}
+
+// MinimockWait waits for all mocked methods to be called the expected number of times
+func (m *ThingNotificationRepositoryMock) MinimockWait(timeout mm_time.Duration) {
+	timeoutCh := mm_time.After(timeout)
+	for {
+		if m.minimockDone() {
+			return
+		}
+		select {
+		case <-timeoutCh:
+			m.MinimockFinish()
+			return
+		case <-mm_time.After(10 * mm_time.Millisecond):
+		}
+	}
+}
+
+func (m *ThingNotificationRepositoryMock) minimockDone() bool {
+	done := true
+	return done &&
+		m.MinimockDeleteDone()
+}

+ 756 - 0
internal/api/v1/place/mocks/thing_repository_minimock.go

@@ -0,0 +1,756 @@
+// Code generated by http://github.com/gojuno/minimock (v3.3.13). DO NOT EDIT.
+
+package mocks
+
+//go:generate minimock -i git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/place.ThingRepository -o thing_repository_minimock.go -n ThingRepositoryMock -p mocks
+
+import (
+	"context"
+	"database/sql"
+	"sync"
+	mm_atomic "sync/atomic"
+	mm_time "time"
+
+	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
+	"github.com/gojuno/minimock/v3"
+)
+
+// ThingRepositoryMock implements place.ThingRepository
+type ThingRepositoryMock struct {
+	t          minimock.Tester
+	finishOnce sync.Once
+
+	funcDelete          func(ctx context.Context, thingID int, tx *sql.Tx) (err error)
+	inspectFuncDelete   func(ctx context.Context, thingID int, tx *sql.Tx)
+	afterDeleteCounter  uint64
+	beforeDeleteCounter uint64
+	DeleteMock          mThingRepositoryMockDelete
+
+	funcGetByPlaceID          func(ctx context.Context, placeID int) (ta1 []models.Thing, err error)
+	inspectFuncGetByPlaceID   func(ctx context.Context, placeID int)
+	afterGetByPlaceIDCounter  uint64
+	beforeGetByPlaceIDCounter uint64
+	GetByPlaceIDMock          mThingRepositoryMockGetByPlaceID
+}
+
+// NewThingRepositoryMock returns a mock for place.ThingRepository
+func NewThingRepositoryMock(t minimock.Tester) *ThingRepositoryMock {
+	m := &ThingRepositoryMock{t: t}
+
+	if controller, ok := t.(minimock.MockController); ok {
+		controller.RegisterMocker(m)
+	}
+
+	m.DeleteMock = mThingRepositoryMockDelete{mock: m}
+	m.DeleteMock.callArgs = []*ThingRepositoryMockDeleteParams{}
+
+	m.GetByPlaceIDMock = mThingRepositoryMockGetByPlaceID{mock: m}
+	m.GetByPlaceIDMock.callArgs = []*ThingRepositoryMockGetByPlaceIDParams{}
+
+	t.Cleanup(m.MinimockFinish)
+
+	return m
+}
+
+type mThingRepositoryMockDelete struct {
+	optional           bool
+	mock               *ThingRepositoryMock
+	defaultExpectation *ThingRepositoryMockDeleteExpectation
+	expectations       []*ThingRepositoryMockDeleteExpectation
+
+	callArgs []*ThingRepositoryMockDeleteParams
+	mutex    sync.RWMutex
+
+	expectedInvocations uint64
+}
+
+// ThingRepositoryMockDeleteExpectation specifies expectation struct of the ThingRepository.Delete
+type ThingRepositoryMockDeleteExpectation struct {
+	mock      *ThingRepositoryMock
+	params    *ThingRepositoryMockDeleteParams
+	paramPtrs *ThingRepositoryMockDeleteParamPtrs
+	results   *ThingRepositoryMockDeleteResults
+	Counter   uint64
+}
+
+// ThingRepositoryMockDeleteParams contains parameters of the ThingRepository.Delete
+type ThingRepositoryMockDeleteParams struct {
+	ctx     context.Context
+	thingID int
+	tx      *sql.Tx
+}
+
+// ThingRepositoryMockDeleteParamPtrs contains pointers to parameters of the ThingRepository.Delete
+type ThingRepositoryMockDeleteParamPtrs struct {
+	ctx     *context.Context
+	thingID *int
+	tx      **sql.Tx
+}
+
+// ThingRepositoryMockDeleteResults contains results of the ThingRepository.Delete
+type ThingRepositoryMockDeleteResults struct {
+	err error
+}
+
+// Marks this method to be optional. The default behavior of any method with Return() is '1 or more', meaning
+// the test will fail minimock's automatic final call check if the mocked method was not called at least once.
+// Optional() makes method check to work in '0 or more' mode.
+// It is NOT RECOMMENDED to use this option unless you really need it, as default behaviour helps to
+// catch the problems when the expected method call is totally skipped during test run.
+func (mmDelete *mThingRepositoryMockDelete) Optional() *mThingRepositoryMockDelete {
+	mmDelete.optional = true
+	return mmDelete
+}
+
+// Expect sets up expected params for ThingRepository.Delete
+func (mmDelete *mThingRepositoryMockDelete) Expect(ctx context.Context, thingID int, tx *sql.Tx) *mThingRepositoryMockDelete {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("ThingRepositoryMock.Delete mock is already set by Set")
+	}
+
+	if mmDelete.defaultExpectation == nil {
+		mmDelete.defaultExpectation = &ThingRepositoryMockDeleteExpectation{}
+	}
+
+	if mmDelete.defaultExpectation.paramPtrs != nil {
+		mmDelete.mock.t.Fatalf("ThingRepositoryMock.Delete mock is already set by ExpectParams functions")
+	}
+
+	mmDelete.defaultExpectation.params = &ThingRepositoryMockDeleteParams{ctx, thingID, tx}
+	for _, e := range mmDelete.expectations {
+		if minimock.Equal(e.params, mmDelete.defaultExpectation.params) {
+			mmDelete.mock.t.Fatalf("Expectation set by When has same params: %#v", *mmDelete.defaultExpectation.params)
+		}
+	}
+
+	return mmDelete
+}
+
+// ExpectCtxParam1 sets up expected param ctx for ThingRepository.Delete
+func (mmDelete *mThingRepositoryMockDelete) ExpectCtxParam1(ctx context.Context) *mThingRepositoryMockDelete {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("ThingRepositoryMock.Delete mock is already set by Set")
+	}
+
+	if mmDelete.defaultExpectation == nil {
+		mmDelete.defaultExpectation = &ThingRepositoryMockDeleteExpectation{}
+	}
+
+	if mmDelete.defaultExpectation.params != nil {
+		mmDelete.mock.t.Fatalf("ThingRepositoryMock.Delete mock is already set by Expect")
+	}
+
+	if mmDelete.defaultExpectation.paramPtrs == nil {
+		mmDelete.defaultExpectation.paramPtrs = &ThingRepositoryMockDeleteParamPtrs{}
+	}
+	mmDelete.defaultExpectation.paramPtrs.ctx = &ctx
+
+	return mmDelete
+}
+
+// ExpectThingIDParam2 sets up expected param thingID for ThingRepository.Delete
+func (mmDelete *mThingRepositoryMockDelete) ExpectThingIDParam2(thingID int) *mThingRepositoryMockDelete {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("ThingRepositoryMock.Delete mock is already set by Set")
+	}
+
+	if mmDelete.defaultExpectation == nil {
+		mmDelete.defaultExpectation = &ThingRepositoryMockDeleteExpectation{}
+	}
+
+	if mmDelete.defaultExpectation.params != nil {
+		mmDelete.mock.t.Fatalf("ThingRepositoryMock.Delete mock is already set by Expect")
+	}
+
+	if mmDelete.defaultExpectation.paramPtrs == nil {
+		mmDelete.defaultExpectation.paramPtrs = &ThingRepositoryMockDeleteParamPtrs{}
+	}
+	mmDelete.defaultExpectation.paramPtrs.thingID = &thingID
+
+	return mmDelete
+}
+
+// ExpectTxParam3 sets up expected param tx for ThingRepository.Delete
+func (mmDelete *mThingRepositoryMockDelete) ExpectTxParam3(tx *sql.Tx) *mThingRepositoryMockDelete {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("ThingRepositoryMock.Delete mock is already set by Set")
+	}
+
+	if mmDelete.defaultExpectation == nil {
+		mmDelete.defaultExpectation = &ThingRepositoryMockDeleteExpectation{}
+	}
+
+	if mmDelete.defaultExpectation.params != nil {
+		mmDelete.mock.t.Fatalf("ThingRepositoryMock.Delete mock is already set by Expect")
+	}
+
+	if mmDelete.defaultExpectation.paramPtrs == nil {
+		mmDelete.defaultExpectation.paramPtrs = &ThingRepositoryMockDeleteParamPtrs{}
+	}
+	mmDelete.defaultExpectation.paramPtrs.tx = &tx
+
+	return mmDelete
+}
+
+// Inspect accepts an inspector function that has same arguments as the ThingRepository.Delete
+func (mmDelete *mThingRepositoryMockDelete) Inspect(f func(ctx context.Context, thingID int, tx *sql.Tx)) *mThingRepositoryMockDelete {
+	if mmDelete.mock.inspectFuncDelete != nil {
+		mmDelete.mock.t.Fatalf("Inspect function is already set for ThingRepositoryMock.Delete")
+	}
+
+	mmDelete.mock.inspectFuncDelete = f
+
+	return mmDelete
+}
+
+// Return sets up results that will be returned by ThingRepository.Delete
+func (mmDelete *mThingRepositoryMockDelete) Return(err error) *ThingRepositoryMock {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("ThingRepositoryMock.Delete mock is already set by Set")
+	}
+
+	if mmDelete.defaultExpectation == nil {
+		mmDelete.defaultExpectation = &ThingRepositoryMockDeleteExpectation{mock: mmDelete.mock}
+	}
+	mmDelete.defaultExpectation.results = &ThingRepositoryMockDeleteResults{err}
+	return mmDelete.mock
+}
+
+// Set uses given function f to mock the ThingRepository.Delete method
+func (mmDelete *mThingRepositoryMockDelete) Set(f func(ctx context.Context, thingID int, tx *sql.Tx) (err error)) *ThingRepositoryMock {
+	if mmDelete.defaultExpectation != nil {
+		mmDelete.mock.t.Fatalf("Default expectation is already set for the ThingRepository.Delete method")
+	}
+
+	if len(mmDelete.expectations) > 0 {
+		mmDelete.mock.t.Fatalf("Some expectations are already set for the ThingRepository.Delete method")
+	}
+
+	mmDelete.mock.funcDelete = f
+	return mmDelete.mock
+}
+
+// When sets expectation for the ThingRepository.Delete which will trigger the result defined by the following
+// Then helper
+func (mmDelete *mThingRepositoryMockDelete) When(ctx context.Context, thingID int, tx *sql.Tx) *ThingRepositoryMockDeleteExpectation {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("ThingRepositoryMock.Delete mock is already set by Set")
+	}
+
+	expectation := &ThingRepositoryMockDeleteExpectation{
+		mock:   mmDelete.mock,
+		params: &ThingRepositoryMockDeleteParams{ctx, thingID, tx},
+	}
+	mmDelete.expectations = append(mmDelete.expectations, expectation)
+	return expectation
+}
+
+// Then sets up ThingRepository.Delete return parameters for the expectation previously defined by the When method
+func (e *ThingRepositoryMockDeleteExpectation) Then(err error) *ThingRepositoryMock {
+	e.results = &ThingRepositoryMockDeleteResults{err}
+	return e.mock
+}
+
+// Times sets number of times ThingRepository.Delete should be invoked
+func (mmDelete *mThingRepositoryMockDelete) Times(n uint64) *mThingRepositoryMockDelete {
+	if n == 0 {
+		mmDelete.mock.t.Fatalf("Times of ThingRepositoryMock.Delete mock can not be zero")
+	}
+	mm_atomic.StoreUint64(&mmDelete.expectedInvocations, n)
+	return mmDelete
+}
+
+func (mmDelete *mThingRepositoryMockDelete) invocationsDone() bool {
+	if len(mmDelete.expectations) == 0 && mmDelete.defaultExpectation == nil && mmDelete.mock.funcDelete == nil {
+		return true
+	}
+
+	totalInvocations := mm_atomic.LoadUint64(&mmDelete.mock.afterDeleteCounter)
+	expectedInvocations := mm_atomic.LoadUint64(&mmDelete.expectedInvocations)
+
+	return totalInvocations > 0 && (expectedInvocations == 0 || expectedInvocations == totalInvocations)
+}
+
+// Delete implements place.ThingRepository
+func (mmDelete *ThingRepositoryMock) Delete(ctx context.Context, thingID int, tx *sql.Tx) (err error) {
+	mm_atomic.AddUint64(&mmDelete.beforeDeleteCounter, 1)
+	defer mm_atomic.AddUint64(&mmDelete.afterDeleteCounter, 1)
+
+	if mmDelete.inspectFuncDelete != nil {
+		mmDelete.inspectFuncDelete(ctx, thingID, tx)
+	}
+
+	mm_params := ThingRepositoryMockDeleteParams{ctx, thingID, tx}
+
+	// Record call args
+	mmDelete.DeleteMock.mutex.Lock()
+	mmDelete.DeleteMock.callArgs = append(mmDelete.DeleteMock.callArgs, &mm_params)
+	mmDelete.DeleteMock.mutex.Unlock()
+
+	for _, e := range mmDelete.DeleteMock.expectations {
+		if minimock.Equal(*e.params, mm_params) {
+			mm_atomic.AddUint64(&e.Counter, 1)
+			return e.results.err
+		}
+	}
+
+	if mmDelete.DeleteMock.defaultExpectation != nil {
+		mm_atomic.AddUint64(&mmDelete.DeleteMock.defaultExpectation.Counter, 1)
+		mm_want := mmDelete.DeleteMock.defaultExpectation.params
+		mm_want_ptrs := mmDelete.DeleteMock.defaultExpectation.paramPtrs
+
+		mm_got := ThingRepositoryMockDeleteParams{ctx, thingID, tx}
+
+		if mm_want_ptrs != nil {
+
+			if mm_want_ptrs.ctx != nil && !minimock.Equal(*mm_want_ptrs.ctx, mm_got.ctx) {
+				mmDelete.t.Errorf("ThingRepositoryMock.Delete got unexpected parameter ctx, want: %#v, got: %#v%s\n", *mm_want_ptrs.ctx, mm_got.ctx, minimock.Diff(*mm_want_ptrs.ctx, mm_got.ctx))
+			}
+
+			if mm_want_ptrs.thingID != nil && !minimock.Equal(*mm_want_ptrs.thingID, mm_got.thingID) {
+				mmDelete.t.Errorf("ThingRepositoryMock.Delete got unexpected parameter thingID, want: %#v, got: %#v%s\n", *mm_want_ptrs.thingID, mm_got.thingID, minimock.Diff(*mm_want_ptrs.thingID, mm_got.thingID))
+			}
+
+			if mm_want_ptrs.tx != nil && !minimock.Equal(*mm_want_ptrs.tx, mm_got.tx) {
+				mmDelete.t.Errorf("ThingRepositoryMock.Delete got unexpected parameter tx, want: %#v, got: %#v%s\n", *mm_want_ptrs.tx, mm_got.tx, minimock.Diff(*mm_want_ptrs.tx, mm_got.tx))
+			}
+
+		} else if mm_want != nil && !minimock.Equal(*mm_want, mm_got) {
+			mmDelete.t.Errorf("ThingRepositoryMock.Delete got unexpected parameters, want: %#v, got: %#v%s\n", *mm_want, mm_got, minimock.Diff(*mm_want, mm_got))
+		}
+
+		mm_results := mmDelete.DeleteMock.defaultExpectation.results
+		if mm_results == nil {
+			mmDelete.t.Fatal("No results are set for the ThingRepositoryMock.Delete")
+		}
+		return (*mm_results).err
+	}
+	if mmDelete.funcDelete != nil {
+		return mmDelete.funcDelete(ctx, thingID, tx)
+	}
+	mmDelete.t.Fatalf("Unexpected call to ThingRepositoryMock.Delete. %v %v %v", ctx, thingID, tx)
+	return
+}
+
+// DeleteAfterCounter returns a count of finished ThingRepositoryMock.Delete invocations
+func (mmDelete *ThingRepositoryMock) DeleteAfterCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmDelete.afterDeleteCounter)
+}
+
+// DeleteBeforeCounter returns a count of ThingRepositoryMock.Delete invocations
+func (mmDelete *ThingRepositoryMock) DeleteBeforeCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmDelete.beforeDeleteCounter)
+}
+
+// Calls returns a list of arguments used in each call to ThingRepositoryMock.Delete.
+// The list is in the same order as the calls were made (i.e. recent calls have a higher index)
+func (mmDelete *mThingRepositoryMockDelete) Calls() []*ThingRepositoryMockDeleteParams {
+	mmDelete.mutex.RLock()
+
+	argCopy := make([]*ThingRepositoryMockDeleteParams, len(mmDelete.callArgs))
+	copy(argCopy, mmDelete.callArgs)
+
+	mmDelete.mutex.RUnlock()
+
+	return argCopy
+}
+
+// MinimockDeleteDone returns true if the count of the Delete invocations corresponds
+// the number of defined expectations
+func (m *ThingRepositoryMock) MinimockDeleteDone() bool {
+	if m.DeleteMock.optional {
+		// Optional methods provide '0 or more' call count restriction.
+		return true
+	}
+
+	for _, e := range m.DeleteMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			return false
+		}
+	}
+
+	return m.DeleteMock.invocationsDone()
+}
+
+// MinimockDeleteInspect logs each unmet expectation
+func (m *ThingRepositoryMock) MinimockDeleteInspect() {
+	for _, e := range m.DeleteMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			m.t.Errorf("Expected call to ThingRepositoryMock.Delete with params: %#v", *e.params)
+		}
+	}
+
+	afterDeleteCounter := mm_atomic.LoadUint64(&m.afterDeleteCounter)
+	// if default expectation was set then invocations count should be greater than zero
+	if m.DeleteMock.defaultExpectation != nil && afterDeleteCounter < 1 {
+		if m.DeleteMock.defaultExpectation.params == nil {
+			m.t.Error("Expected call to ThingRepositoryMock.Delete")
+		} else {
+			m.t.Errorf("Expected call to ThingRepositoryMock.Delete with params: %#v", *m.DeleteMock.defaultExpectation.params)
+		}
+	}
+	// if func was set then invocations count should be greater than zero
+	if m.funcDelete != nil && afterDeleteCounter < 1 {
+		m.t.Error("Expected call to ThingRepositoryMock.Delete")
+	}
+
+	if !m.DeleteMock.invocationsDone() && afterDeleteCounter > 0 {
+		m.t.Errorf("Expected %d calls to ThingRepositoryMock.Delete but found %d calls",
+			mm_atomic.LoadUint64(&m.DeleteMock.expectedInvocations), afterDeleteCounter)
+	}
+}
+
+type mThingRepositoryMockGetByPlaceID struct {
+	optional           bool
+	mock               *ThingRepositoryMock
+	defaultExpectation *ThingRepositoryMockGetByPlaceIDExpectation
+	expectations       []*ThingRepositoryMockGetByPlaceIDExpectation
+
+	callArgs []*ThingRepositoryMockGetByPlaceIDParams
+	mutex    sync.RWMutex
+
+	expectedInvocations uint64
+}
+
+// ThingRepositoryMockGetByPlaceIDExpectation specifies expectation struct of the ThingRepository.GetByPlaceID
+type ThingRepositoryMockGetByPlaceIDExpectation struct {
+	mock      *ThingRepositoryMock
+	params    *ThingRepositoryMockGetByPlaceIDParams
+	paramPtrs *ThingRepositoryMockGetByPlaceIDParamPtrs
+	results   *ThingRepositoryMockGetByPlaceIDResults
+	Counter   uint64
+}
+
+// ThingRepositoryMockGetByPlaceIDParams contains parameters of the ThingRepository.GetByPlaceID
+type ThingRepositoryMockGetByPlaceIDParams struct {
+	ctx     context.Context
+	placeID int
+}
+
+// ThingRepositoryMockGetByPlaceIDParamPtrs contains pointers to parameters of the ThingRepository.GetByPlaceID
+type ThingRepositoryMockGetByPlaceIDParamPtrs struct {
+	ctx     *context.Context
+	placeID *int
+}
+
+// ThingRepositoryMockGetByPlaceIDResults contains results of the ThingRepository.GetByPlaceID
+type ThingRepositoryMockGetByPlaceIDResults struct {
+	ta1 []models.Thing
+	err error
+}
+
+// Marks this method to be optional. The default behavior of any method with Return() is '1 or more', meaning
+// the test will fail minimock's automatic final call check if the mocked method was not called at least once.
+// Optional() makes method check to work in '0 or more' mode.
+// It is NOT RECOMMENDED to use this option unless you really need it, as default behaviour helps to
+// catch the problems when the expected method call is totally skipped during test run.
+func (mmGetByPlaceID *mThingRepositoryMockGetByPlaceID) Optional() *mThingRepositoryMockGetByPlaceID {
+	mmGetByPlaceID.optional = true
+	return mmGetByPlaceID
+}
+
+// Expect sets up expected params for ThingRepository.GetByPlaceID
+func (mmGetByPlaceID *mThingRepositoryMockGetByPlaceID) Expect(ctx context.Context, placeID int) *mThingRepositoryMockGetByPlaceID {
+	if mmGetByPlaceID.mock.funcGetByPlaceID != nil {
+		mmGetByPlaceID.mock.t.Fatalf("ThingRepositoryMock.GetByPlaceID mock is already set by Set")
+	}
+
+	if mmGetByPlaceID.defaultExpectation == nil {
+		mmGetByPlaceID.defaultExpectation = &ThingRepositoryMockGetByPlaceIDExpectation{}
+	}
+
+	if mmGetByPlaceID.defaultExpectation.paramPtrs != nil {
+		mmGetByPlaceID.mock.t.Fatalf("ThingRepositoryMock.GetByPlaceID mock is already set by ExpectParams functions")
+	}
+
+	mmGetByPlaceID.defaultExpectation.params = &ThingRepositoryMockGetByPlaceIDParams{ctx, placeID}
+	for _, e := range mmGetByPlaceID.expectations {
+		if minimock.Equal(e.params, mmGetByPlaceID.defaultExpectation.params) {
+			mmGetByPlaceID.mock.t.Fatalf("Expectation set by When has same params: %#v", *mmGetByPlaceID.defaultExpectation.params)
+		}
+	}
+
+	return mmGetByPlaceID
+}
+
+// ExpectCtxParam1 sets up expected param ctx for ThingRepository.GetByPlaceID
+func (mmGetByPlaceID *mThingRepositoryMockGetByPlaceID) ExpectCtxParam1(ctx context.Context) *mThingRepositoryMockGetByPlaceID {
+	if mmGetByPlaceID.mock.funcGetByPlaceID != nil {
+		mmGetByPlaceID.mock.t.Fatalf("ThingRepositoryMock.GetByPlaceID mock is already set by Set")
+	}
+
+	if mmGetByPlaceID.defaultExpectation == nil {
+		mmGetByPlaceID.defaultExpectation = &ThingRepositoryMockGetByPlaceIDExpectation{}
+	}
+
+	if mmGetByPlaceID.defaultExpectation.params != nil {
+		mmGetByPlaceID.mock.t.Fatalf("ThingRepositoryMock.GetByPlaceID mock is already set by Expect")
+	}
+
+	if mmGetByPlaceID.defaultExpectation.paramPtrs == nil {
+		mmGetByPlaceID.defaultExpectation.paramPtrs = &ThingRepositoryMockGetByPlaceIDParamPtrs{}
+	}
+	mmGetByPlaceID.defaultExpectation.paramPtrs.ctx = &ctx
+
+	return mmGetByPlaceID
+}
+
+// ExpectPlaceIDParam2 sets up expected param placeID for ThingRepository.GetByPlaceID
+func (mmGetByPlaceID *mThingRepositoryMockGetByPlaceID) ExpectPlaceIDParam2(placeID int) *mThingRepositoryMockGetByPlaceID {
+	if mmGetByPlaceID.mock.funcGetByPlaceID != nil {
+		mmGetByPlaceID.mock.t.Fatalf("ThingRepositoryMock.GetByPlaceID mock is already set by Set")
+	}
+
+	if mmGetByPlaceID.defaultExpectation == nil {
+		mmGetByPlaceID.defaultExpectation = &ThingRepositoryMockGetByPlaceIDExpectation{}
+	}
+
+	if mmGetByPlaceID.defaultExpectation.params != nil {
+		mmGetByPlaceID.mock.t.Fatalf("ThingRepositoryMock.GetByPlaceID mock is already set by Expect")
+	}
+
+	if mmGetByPlaceID.defaultExpectation.paramPtrs == nil {
+		mmGetByPlaceID.defaultExpectation.paramPtrs = &ThingRepositoryMockGetByPlaceIDParamPtrs{}
+	}
+	mmGetByPlaceID.defaultExpectation.paramPtrs.placeID = &placeID
+
+	return mmGetByPlaceID
+}
+
+// Inspect accepts an inspector function that has same arguments as the ThingRepository.GetByPlaceID
+func (mmGetByPlaceID *mThingRepositoryMockGetByPlaceID) Inspect(f func(ctx context.Context, placeID int)) *mThingRepositoryMockGetByPlaceID {
+	if mmGetByPlaceID.mock.inspectFuncGetByPlaceID != nil {
+		mmGetByPlaceID.mock.t.Fatalf("Inspect function is already set for ThingRepositoryMock.GetByPlaceID")
+	}
+
+	mmGetByPlaceID.mock.inspectFuncGetByPlaceID = f
+
+	return mmGetByPlaceID
+}
+
+// Return sets up results that will be returned by ThingRepository.GetByPlaceID
+func (mmGetByPlaceID *mThingRepositoryMockGetByPlaceID) Return(ta1 []models.Thing, err error) *ThingRepositoryMock {
+	if mmGetByPlaceID.mock.funcGetByPlaceID != nil {
+		mmGetByPlaceID.mock.t.Fatalf("ThingRepositoryMock.GetByPlaceID mock is already set by Set")
+	}
+
+	if mmGetByPlaceID.defaultExpectation == nil {
+		mmGetByPlaceID.defaultExpectation = &ThingRepositoryMockGetByPlaceIDExpectation{mock: mmGetByPlaceID.mock}
+	}
+	mmGetByPlaceID.defaultExpectation.results = &ThingRepositoryMockGetByPlaceIDResults{ta1, err}
+	return mmGetByPlaceID.mock
+}
+
+// Set uses given function f to mock the ThingRepository.GetByPlaceID method
+func (mmGetByPlaceID *mThingRepositoryMockGetByPlaceID) Set(f func(ctx context.Context, placeID int) (ta1 []models.Thing, err error)) *ThingRepositoryMock {
+	if mmGetByPlaceID.defaultExpectation != nil {
+		mmGetByPlaceID.mock.t.Fatalf("Default expectation is already set for the ThingRepository.GetByPlaceID method")
+	}
+
+	if len(mmGetByPlaceID.expectations) > 0 {
+		mmGetByPlaceID.mock.t.Fatalf("Some expectations are already set for the ThingRepository.GetByPlaceID method")
+	}
+
+	mmGetByPlaceID.mock.funcGetByPlaceID = f
+	return mmGetByPlaceID.mock
+}
+
+// When sets expectation for the ThingRepository.GetByPlaceID which will trigger the result defined by the following
+// Then helper
+func (mmGetByPlaceID *mThingRepositoryMockGetByPlaceID) When(ctx context.Context, placeID int) *ThingRepositoryMockGetByPlaceIDExpectation {
+	if mmGetByPlaceID.mock.funcGetByPlaceID != nil {
+		mmGetByPlaceID.mock.t.Fatalf("ThingRepositoryMock.GetByPlaceID mock is already set by Set")
+	}
+
+	expectation := &ThingRepositoryMockGetByPlaceIDExpectation{
+		mock:   mmGetByPlaceID.mock,
+		params: &ThingRepositoryMockGetByPlaceIDParams{ctx, placeID},
+	}
+	mmGetByPlaceID.expectations = append(mmGetByPlaceID.expectations, expectation)
+	return expectation
+}
+
+// Then sets up ThingRepository.GetByPlaceID return parameters for the expectation previously defined by the When method
+func (e *ThingRepositoryMockGetByPlaceIDExpectation) Then(ta1 []models.Thing, err error) *ThingRepositoryMock {
+	e.results = &ThingRepositoryMockGetByPlaceIDResults{ta1, err}
+	return e.mock
+}
+
+// Times sets number of times ThingRepository.GetByPlaceID should be invoked
+func (mmGetByPlaceID *mThingRepositoryMockGetByPlaceID) Times(n uint64) *mThingRepositoryMockGetByPlaceID {
+	if n == 0 {
+		mmGetByPlaceID.mock.t.Fatalf("Times of ThingRepositoryMock.GetByPlaceID mock can not be zero")
+	}
+	mm_atomic.StoreUint64(&mmGetByPlaceID.expectedInvocations, n)
+	return mmGetByPlaceID
+}
+
+func (mmGetByPlaceID *mThingRepositoryMockGetByPlaceID) invocationsDone() bool {
+	if len(mmGetByPlaceID.expectations) == 0 && mmGetByPlaceID.defaultExpectation == nil && mmGetByPlaceID.mock.funcGetByPlaceID == nil {
+		return true
+	}
+
+	totalInvocations := mm_atomic.LoadUint64(&mmGetByPlaceID.mock.afterGetByPlaceIDCounter)
+	expectedInvocations := mm_atomic.LoadUint64(&mmGetByPlaceID.expectedInvocations)
+
+	return totalInvocations > 0 && (expectedInvocations == 0 || expectedInvocations == totalInvocations)
+}
+
+// GetByPlaceID implements place.ThingRepository
+func (mmGetByPlaceID *ThingRepositoryMock) GetByPlaceID(ctx context.Context, placeID int) (ta1 []models.Thing, err error) {
+	mm_atomic.AddUint64(&mmGetByPlaceID.beforeGetByPlaceIDCounter, 1)
+	defer mm_atomic.AddUint64(&mmGetByPlaceID.afterGetByPlaceIDCounter, 1)
+
+	if mmGetByPlaceID.inspectFuncGetByPlaceID != nil {
+		mmGetByPlaceID.inspectFuncGetByPlaceID(ctx, placeID)
+	}
+
+	mm_params := ThingRepositoryMockGetByPlaceIDParams{ctx, placeID}
+
+	// Record call args
+	mmGetByPlaceID.GetByPlaceIDMock.mutex.Lock()
+	mmGetByPlaceID.GetByPlaceIDMock.callArgs = append(mmGetByPlaceID.GetByPlaceIDMock.callArgs, &mm_params)
+	mmGetByPlaceID.GetByPlaceIDMock.mutex.Unlock()
+
+	for _, e := range mmGetByPlaceID.GetByPlaceIDMock.expectations {
+		if minimock.Equal(*e.params, mm_params) {
+			mm_atomic.AddUint64(&e.Counter, 1)
+			return e.results.ta1, e.results.err
+		}
+	}
+
+	if mmGetByPlaceID.GetByPlaceIDMock.defaultExpectation != nil {
+		mm_atomic.AddUint64(&mmGetByPlaceID.GetByPlaceIDMock.defaultExpectation.Counter, 1)
+		mm_want := mmGetByPlaceID.GetByPlaceIDMock.defaultExpectation.params
+		mm_want_ptrs := mmGetByPlaceID.GetByPlaceIDMock.defaultExpectation.paramPtrs
+
+		mm_got := ThingRepositoryMockGetByPlaceIDParams{ctx, placeID}
+
+		if mm_want_ptrs != nil {
+
+			if mm_want_ptrs.ctx != nil && !minimock.Equal(*mm_want_ptrs.ctx, mm_got.ctx) {
+				mmGetByPlaceID.t.Errorf("ThingRepositoryMock.GetByPlaceID got unexpected parameter ctx, want: %#v, got: %#v%s\n", *mm_want_ptrs.ctx, mm_got.ctx, minimock.Diff(*mm_want_ptrs.ctx, mm_got.ctx))
+			}
+
+			if mm_want_ptrs.placeID != nil && !minimock.Equal(*mm_want_ptrs.placeID, mm_got.placeID) {
+				mmGetByPlaceID.t.Errorf("ThingRepositoryMock.GetByPlaceID got unexpected parameter placeID, want: %#v, got: %#v%s\n", *mm_want_ptrs.placeID, mm_got.placeID, minimock.Diff(*mm_want_ptrs.placeID, mm_got.placeID))
+			}
+
+		} else if mm_want != nil && !minimock.Equal(*mm_want, mm_got) {
+			mmGetByPlaceID.t.Errorf("ThingRepositoryMock.GetByPlaceID got unexpected parameters, want: %#v, got: %#v%s\n", *mm_want, mm_got, minimock.Diff(*mm_want, mm_got))
+		}
+
+		mm_results := mmGetByPlaceID.GetByPlaceIDMock.defaultExpectation.results
+		if mm_results == nil {
+			mmGetByPlaceID.t.Fatal("No results are set for the ThingRepositoryMock.GetByPlaceID")
+		}
+		return (*mm_results).ta1, (*mm_results).err
+	}
+	if mmGetByPlaceID.funcGetByPlaceID != nil {
+		return mmGetByPlaceID.funcGetByPlaceID(ctx, placeID)
+	}
+	mmGetByPlaceID.t.Fatalf("Unexpected call to ThingRepositoryMock.GetByPlaceID. %v %v", ctx, placeID)
+	return
+}
+
+// GetByPlaceIDAfterCounter returns a count of finished ThingRepositoryMock.GetByPlaceID invocations
+func (mmGetByPlaceID *ThingRepositoryMock) GetByPlaceIDAfterCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmGetByPlaceID.afterGetByPlaceIDCounter)
+}
+
+// GetByPlaceIDBeforeCounter returns a count of ThingRepositoryMock.GetByPlaceID invocations
+func (mmGetByPlaceID *ThingRepositoryMock) GetByPlaceIDBeforeCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmGetByPlaceID.beforeGetByPlaceIDCounter)
+}
+
+// Calls returns a list of arguments used in each call to ThingRepositoryMock.GetByPlaceID.
+// The list is in the same order as the calls were made (i.e. recent calls have a higher index)
+func (mmGetByPlaceID *mThingRepositoryMockGetByPlaceID) Calls() []*ThingRepositoryMockGetByPlaceIDParams {
+	mmGetByPlaceID.mutex.RLock()
+
+	argCopy := make([]*ThingRepositoryMockGetByPlaceIDParams, len(mmGetByPlaceID.callArgs))
+	copy(argCopy, mmGetByPlaceID.callArgs)
+
+	mmGetByPlaceID.mutex.RUnlock()
+
+	return argCopy
+}
+
+// MinimockGetByPlaceIDDone returns true if the count of the GetByPlaceID invocations corresponds
+// the number of defined expectations
+func (m *ThingRepositoryMock) MinimockGetByPlaceIDDone() bool {
+	if m.GetByPlaceIDMock.optional {
+		// Optional methods provide '0 or more' call count restriction.
+		return true
+	}
+
+	for _, e := range m.GetByPlaceIDMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			return false
+		}
+	}
+
+	return m.GetByPlaceIDMock.invocationsDone()
+}
+
+// MinimockGetByPlaceIDInspect logs each unmet expectation
+func (m *ThingRepositoryMock) MinimockGetByPlaceIDInspect() {
+	for _, e := range m.GetByPlaceIDMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			m.t.Errorf("Expected call to ThingRepositoryMock.GetByPlaceID with params: %#v", *e.params)
+		}
+	}
+
+	afterGetByPlaceIDCounter := mm_atomic.LoadUint64(&m.afterGetByPlaceIDCounter)
+	// if default expectation was set then invocations count should be greater than zero
+	if m.GetByPlaceIDMock.defaultExpectation != nil && afterGetByPlaceIDCounter < 1 {
+		if m.GetByPlaceIDMock.defaultExpectation.params == nil {
+			m.t.Error("Expected call to ThingRepositoryMock.GetByPlaceID")
+		} else {
+			m.t.Errorf("Expected call to ThingRepositoryMock.GetByPlaceID with params: %#v", *m.GetByPlaceIDMock.defaultExpectation.params)
+		}
+	}
+	// if func was set then invocations count should be greater than zero
+	if m.funcGetByPlaceID != nil && afterGetByPlaceIDCounter < 1 {
+		m.t.Error("Expected call to ThingRepositoryMock.GetByPlaceID")
+	}
+
+	if !m.GetByPlaceIDMock.invocationsDone() && afterGetByPlaceIDCounter > 0 {
+		m.t.Errorf("Expected %d calls to ThingRepositoryMock.GetByPlaceID but found %d calls",
+			mm_atomic.LoadUint64(&m.GetByPlaceIDMock.expectedInvocations), afterGetByPlaceIDCounter)
+	}
+}
+
+// MinimockFinish checks that all mocked methods have been called the expected number of times
+func (m *ThingRepositoryMock) MinimockFinish() {
+	m.finishOnce.Do(func() {
+		if !m.minimockDone() {
+			m.MinimockDeleteInspect()
+
+			m.MinimockGetByPlaceIDInspect()
+		}
+	})
+}
+
+// MinimockWait waits for all mocked methods to be called the expected number of times
+func (m *ThingRepositoryMock) MinimockWait(timeout mm_time.Duration) {
+	timeoutCh := mm_time.After(timeout)
+	for {
+		if m.minimockDone() {
+			return
+		}
+		select {
+		case <-timeoutCh:
+			m.MinimockFinish()
+			return
+		case <-mm_time.After(10 * mm_time.Millisecond):
+		}
+	}
+}
+
+func (m *ThingRepositoryMock) minimockDone() bool {
+	done := true
+	return done &&
+		m.MinimockDeleteDone() &&
+		m.MinimockGetByPlaceIDDone()
+}

+ 422 - 0
internal/api/v1/place/mocks/thing_tag_repository_minimock.go

@@ -0,0 +1,422 @@
+// Code generated by http://github.com/gojuno/minimock (v3.3.13). DO NOT EDIT.
+
+package mocks
+
+//go:generate minimock -i git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/place.ThingTagRepository -o thing_tag_repository_minimock.go -n ThingTagRepositoryMock -p mocks
+
+import (
+	"context"
+	"database/sql"
+	"sync"
+	mm_atomic "sync/atomic"
+	mm_time "time"
+
+	"github.com/gojuno/minimock/v3"
+)
+
+// ThingTagRepositoryMock implements place.ThingTagRepository
+type ThingTagRepositoryMock struct {
+	t          minimock.Tester
+	finishOnce sync.Once
+
+	funcDeleteByThingID          func(ctx context.Context, thingID int, tx *sql.Tx) (err error)
+	inspectFuncDeleteByThingID   func(ctx context.Context, thingID int, tx *sql.Tx)
+	afterDeleteByThingIDCounter  uint64
+	beforeDeleteByThingIDCounter uint64
+	DeleteByThingIDMock          mThingTagRepositoryMockDeleteByThingID
+}
+
+// NewThingTagRepositoryMock returns a mock for place.ThingTagRepository
+func NewThingTagRepositoryMock(t minimock.Tester) *ThingTagRepositoryMock {
+	m := &ThingTagRepositoryMock{t: t}
+
+	if controller, ok := t.(minimock.MockController); ok {
+		controller.RegisterMocker(m)
+	}
+
+	m.DeleteByThingIDMock = mThingTagRepositoryMockDeleteByThingID{mock: m}
+	m.DeleteByThingIDMock.callArgs = []*ThingTagRepositoryMockDeleteByThingIDParams{}
+
+	t.Cleanup(m.MinimockFinish)
+
+	return m
+}
+
+type mThingTagRepositoryMockDeleteByThingID struct {
+	optional           bool
+	mock               *ThingTagRepositoryMock
+	defaultExpectation *ThingTagRepositoryMockDeleteByThingIDExpectation
+	expectations       []*ThingTagRepositoryMockDeleteByThingIDExpectation
+
+	callArgs []*ThingTagRepositoryMockDeleteByThingIDParams
+	mutex    sync.RWMutex
+
+	expectedInvocations uint64
+}
+
+// ThingTagRepositoryMockDeleteByThingIDExpectation specifies expectation struct of the ThingTagRepository.DeleteByThingID
+type ThingTagRepositoryMockDeleteByThingIDExpectation struct {
+	mock      *ThingTagRepositoryMock
+	params    *ThingTagRepositoryMockDeleteByThingIDParams
+	paramPtrs *ThingTagRepositoryMockDeleteByThingIDParamPtrs
+	results   *ThingTagRepositoryMockDeleteByThingIDResults
+	Counter   uint64
+}
+
+// ThingTagRepositoryMockDeleteByThingIDParams contains parameters of the ThingTagRepository.DeleteByThingID
+type ThingTagRepositoryMockDeleteByThingIDParams struct {
+	ctx     context.Context
+	thingID int
+	tx      *sql.Tx
+}
+
+// ThingTagRepositoryMockDeleteByThingIDParamPtrs contains pointers to parameters of the ThingTagRepository.DeleteByThingID
+type ThingTagRepositoryMockDeleteByThingIDParamPtrs struct {
+	ctx     *context.Context
+	thingID *int
+	tx      **sql.Tx
+}
+
+// ThingTagRepositoryMockDeleteByThingIDResults contains results of the ThingTagRepository.DeleteByThingID
+type ThingTagRepositoryMockDeleteByThingIDResults struct {
+	err error
+}
+
+// Marks this method to be optional. The default behavior of any method with Return() is '1 or more', meaning
+// the test will fail minimock's automatic final call check if the mocked method was not called at least once.
+// Optional() makes method check to work in '0 or more' mode.
+// It is NOT RECOMMENDED to use this option unless you really need it, as default behaviour helps to
+// catch the problems when the expected method call is totally skipped during test run.
+func (mmDeleteByThingID *mThingTagRepositoryMockDeleteByThingID) Optional() *mThingTagRepositoryMockDeleteByThingID {
+	mmDeleteByThingID.optional = true
+	return mmDeleteByThingID
+}
+
+// Expect sets up expected params for ThingTagRepository.DeleteByThingID
+func (mmDeleteByThingID *mThingTagRepositoryMockDeleteByThingID) Expect(ctx context.Context, thingID int, tx *sql.Tx) *mThingTagRepositoryMockDeleteByThingID {
+	if mmDeleteByThingID.mock.funcDeleteByThingID != nil {
+		mmDeleteByThingID.mock.t.Fatalf("ThingTagRepositoryMock.DeleteByThingID mock is already set by Set")
+	}
+
+	if mmDeleteByThingID.defaultExpectation == nil {
+		mmDeleteByThingID.defaultExpectation = &ThingTagRepositoryMockDeleteByThingIDExpectation{}
+	}
+
+	if mmDeleteByThingID.defaultExpectation.paramPtrs != nil {
+		mmDeleteByThingID.mock.t.Fatalf("ThingTagRepositoryMock.DeleteByThingID mock is already set by ExpectParams functions")
+	}
+
+	mmDeleteByThingID.defaultExpectation.params = &ThingTagRepositoryMockDeleteByThingIDParams{ctx, thingID, tx}
+	for _, e := range mmDeleteByThingID.expectations {
+		if minimock.Equal(e.params, mmDeleteByThingID.defaultExpectation.params) {
+			mmDeleteByThingID.mock.t.Fatalf("Expectation set by When has same params: %#v", *mmDeleteByThingID.defaultExpectation.params)
+		}
+	}
+
+	return mmDeleteByThingID
+}
+
+// ExpectCtxParam1 sets up expected param ctx for ThingTagRepository.DeleteByThingID
+func (mmDeleteByThingID *mThingTagRepositoryMockDeleteByThingID) ExpectCtxParam1(ctx context.Context) *mThingTagRepositoryMockDeleteByThingID {
+	if mmDeleteByThingID.mock.funcDeleteByThingID != nil {
+		mmDeleteByThingID.mock.t.Fatalf("ThingTagRepositoryMock.DeleteByThingID mock is already set by Set")
+	}
+
+	if mmDeleteByThingID.defaultExpectation == nil {
+		mmDeleteByThingID.defaultExpectation = &ThingTagRepositoryMockDeleteByThingIDExpectation{}
+	}
+
+	if mmDeleteByThingID.defaultExpectation.params != nil {
+		mmDeleteByThingID.mock.t.Fatalf("ThingTagRepositoryMock.DeleteByThingID mock is already set by Expect")
+	}
+
+	if mmDeleteByThingID.defaultExpectation.paramPtrs == nil {
+		mmDeleteByThingID.defaultExpectation.paramPtrs = &ThingTagRepositoryMockDeleteByThingIDParamPtrs{}
+	}
+	mmDeleteByThingID.defaultExpectation.paramPtrs.ctx = &ctx
+
+	return mmDeleteByThingID
+}
+
+// ExpectThingIDParam2 sets up expected param thingID for ThingTagRepository.DeleteByThingID
+func (mmDeleteByThingID *mThingTagRepositoryMockDeleteByThingID) ExpectThingIDParam2(thingID int) *mThingTagRepositoryMockDeleteByThingID {
+	if mmDeleteByThingID.mock.funcDeleteByThingID != nil {
+		mmDeleteByThingID.mock.t.Fatalf("ThingTagRepositoryMock.DeleteByThingID mock is already set by Set")
+	}
+
+	if mmDeleteByThingID.defaultExpectation == nil {
+		mmDeleteByThingID.defaultExpectation = &ThingTagRepositoryMockDeleteByThingIDExpectation{}
+	}
+
+	if mmDeleteByThingID.defaultExpectation.params != nil {
+		mmDeleteByThingID.mock.t.Fatalf("ThingTagRepositoryMock.DeleteByThingID mock is already set by Expect")
+	}
+
+	if mmDeleteByThingID.defaultExpectation.paramPtrs == nil {
+		mmDeleteByThingID.defaultExpectation.paramPtrs = &ThingTagRepositoryMockDeleteByThingIDParamPtrs{}
+	}
+	mmDeleteByThingID.defaultExpectation.paramPtrs.thingID = &thingID
+
+	return mmDeleteByThingID
+}
+
+// ExpectTxParam3 sets up expected param tx for ThingTagRepository.DeleteByThingID
+func (mmDeleteByThingID *mThingTagRepositoryMockDeleteByThingID) ExpectTxParam3(tx *sql.Tx) *mThingTagRepositoryMockDeleteByThingID {
+	if mmDeleteByThingID.mock.funcDeleteByThingID != nil {
+		mmDeleteByThingID.mock.t.Fatalf("ThingTagRepositoryMock.DeleteByThingID mock is already set by Set")
+	}
+
+	if mmDeleteByThingID.defaultExpectation == nil {
+		mmDeleteByThingID.defaultExpectation = &ThingTagRepositoryMockDeleteByThingIDExpectation{}
+	}
+
+	if mmDeleteByThingID.defaultExpectation.params != nil {
+		mmDeleteByThingID.mock.t.Fatalf("ThingTagRepositoryMock.DeleteByThingID mock is already set by Expect")
+	}
+
+	if mmDeleteByThingID.defaultExpectation.paramPtrs == nil {
+		mmDeleteByThingID.defaultExpectation.paramPtrs = &ThingTagRepositoryMockDeleteByThingIDParamPtrs{}
+	}
+	mmDeleteByThingID.defaultExpectation.paramPtrs.tx = &tx
+
+	return mmDeleteByThingID
+}
+
+// Inspect accepts an inspector function that has same arguments as the ThingTagRepository.DeleteByThingID
+func (mmDeleteByThingID *mThingTagRepositoryMockDeleteByThingID) Inspect(f func(ctx context.Context, thingID int, tx *sql.Tx)) *mThingTagRepositoryMockDeleteByThingID {
+	if mmDeleteByThingID.mock.inspectFuncDeleteByThingID != nil {
+		mmDeleteByThingID.mock.t.Fatalf("Inspect function is already set for ThingTagRepositoryMock.DeleteByThingID")
+	}
+
+	mmDeleteByThingID.mock.inspectFuncDeleteByThingID = f
+
+	return mmDeleteByThingID
+}
+
+// Return sets up results that will be returned by ThingTagRepository.DeleteByThingID
+func (mmDeleteByThingID *mThingTagRepositoryMockDeleteByThingID) Return(err error) *ThingTagRepositoryMock {
+	if mmDeleteByThingID.mock.funcDeleteByThingID != nil {
+		mmDeleteByThingID.mock.t.Fatalf("ThingTagRepositoryMock.DeleteByThingID mock is already set by Set")
+	}
+
+	if mmDeleteByThingID.defaultExpectation == nil {
+		mmDeleteByThingID.defaultExpectation = &ThingTagRepositoryMockDeleteByThingIDExpectation{mock: mmDeleteByThingID.mock}
+	}
+	mmDeleteByThingID.defaultExpectation.results = &ThingTagRepositoryMockDeleteByThingIDResults{err}
+	return mmDeleteByThingID.mock
+}
+
+// Set uses given function f to mock the ThingTagRepository.DeleteByThingID method
+func (mmDeleteByThingID *mThingTagRepositoryMockDeleteByThingID) Set(f func(ctx context.Context, thingID int, tx *sql.Tx) (err error)) *ThingTagRepositoryMock {
+	if mmDeleteByThingID.defaultExpectation != nil {
+		mmDeleteByThingID.mock.t.Fatalf("Default expectation is already set for the ThingTagRepository.DeleteByThingID method")
+	}
+
+	if len(mmDeleteByThingID.expectations) > 0 {
+		mmDeleteByThingID.mock.t.Fatalf("Some expectations are already set for the ThingTagRepository.DeleteByThingID method")
+	}
+
+	mmDeleteByThingID.mock.funcDeleteByThingID = f
+	return mmDeleteByThingID.mock
+}
+
+// When sets expectation for the ThingTagRepository.DeleteByThingID which will trigger the result defined by the following
+// Then helper
+func (mmDeleteByThingID *mThingTagRepositoryMockDeleteByThingID) When(ctx context.Context, thingID int, tx *sql.Tx) *ThingTagRepositoryMockDeleteByThingIDExpectation {
+	if mmDeleteByThingID.mock.funcDeleteByThingID != nil {
+		mmDeleteByThingID.mock.t.Fatalf("ThingTagRepositoryMock.DeleteByThingID mock is already set by Set")
+	}
+
+	expectation := &ThingTagRepositoryMockDeleteByThingIDExpectation{
+		mock:   mmDeleteByThingID.mock,
+		params: &ThingTagRepositoryMockDeleteByThingIDParams{ctx, thingID, tx},
+	}
+	mmDeleteByThingID.expectations = append(mmDeleteByThingID.expectations, expectation)
+	return expectation
+}
+
+// Then sets up ThingTagRepository.DeleteByThingID return parameters for the expectation previously defined by the When method
+func (e *ThingTagRepositoryMockDeleteByThingIDExpectation) Then(err error) *ThingTagRepositoryMock {
+	e.results = &ThingTagRepositoryMockDeleteByThingIDResults{err}
+	return e.mock
+}
+
+// Times sets number of times ThingTagRepository.DeleteByThingID should be invoked
+func (mmDeleteByThingID *mThingTagRepositoryMockDeleteByThingID) Times(n uint64) *mThingTagRepositoryMockDeleteByThingID {
+	if n == 0 {
+		mmDeleteByThingID.mock.t.Fatalf("Times of ThingTagRepositoryMock.DeleteByThingID mock can not be zero")
+	}
+	mm_atomic.StoreUint64(&mmDeleteByThingID.expectedInvocations, n)
+	return mmDeleteByThingID
+}
+
+func (mmDeleteByThingID *mThingTagRepositoryMockDeleteByThingID) invocationsDone() bool {
+	if len(mmDeleteByThingID.expectations) == 0 && mmDeleteByThingID.defaultExpectation == nil && mmDeleteByThingID.mock.funcDeleteByThingID == nil {
+		return true
+	}
+
+	totalInvocations := mm_atomic.LoadUint64(&mmDeleteByThingID.mock.afterDeleteByThingIDCounter)
+	expectedInvocations := mm_atomic.LoadUint64(&mmDeleteByThingID.expectedInvocations)
+
+	return totalInvocations > 0 && (expectedInvocations == 0 || expectedInvocations == totalInvocations)
+}
+
+// DeleteByThingID implements place.ThingTagRepository
+func (mmDeleteByThingID *ThingTagRepositoryMock) DeleteByThingID(ctx context.Context, thingID int, tx *sql.Tx) (err error) {
+	mm_atomic.AddUint64(&mmDeleteByThingID.beforeDeleteByThingIDCounter, 1)
+	defer mm_atomic.AddUint64(&mmDeleteByThingID.afterDeleteByThingIDCounter, 1)
+
+	if mmDeleteByThingID.inspectFuncDeleteByThingID != nil {
+		mmDeleteByThingID.inspectFuncDeleteByThingID(ctx, thingID, tx)
+	}
+
+	mm_params := ThingTagRepositoryMockDeleteByThingIDParams{ctx, thingID, tx}
+
+	// Record call args
+	mmDeleteByThingID.DeleteByThingIDMock.mutex.Lock()
+	mmDeleteByThingID.DeleteByThingIDMock.callArgs = append(mmDeleteByThingID.DeleteByThingIDMock.callArgs, &mm_params)
+	mmDeleteByThingID.DeleteByThingIDMock.mutex.Unlock()
+
+	for _, e := range mmDeleteByThingID.DeleteByThingIDMock.expectations {
+		if minimock.Equal(*e.params, mm_params) {
+			mm_atomic.AddUint64(&e.Counter, 1)
+			return e.results.err
+		}
+	}
+
+	if mmDeleteByThingID.DeleteByThingIDMock.defaultExpectation != nil {
+		mm_atomic.AddUint64(&mmDeleteByThingID.DeleteByThingIDMock.defaultExpectation.Counter, 1)
+		mm_want := mmDeleteByThingID.DeleteByThingIDMock.defaultExpectation.params
+		mm_want_ptrs := mmDeleteByThingID.DeleteByThingIDMock.defaultExpectation.paramPtrs
+
+		mm_got := ThingTagRepositoryMockDeleteByThingIDParams{ctx, thingID, tx}
+
+		if mm_want_ptrs != nil {
+
+			if mm_want_ptrs.ctx != nil && !minimock.Equal(*mm_want_ptrs.ctx, mm_got.ctx) {
+				mmDeleteByThingID.t.Errorf("ThingTagRepositoryMock.DeleteByThingID got unexpected parameter ctx, want: %#v, got: %#v%s\n", *mm_want_ptrs.ctx, mm_got.ctx, minimock.Diff(*mm_want_ptrs.ctx, mm_got.ctx))
+			}
+
+			if mm_want_ptrs.thingID != nil && !minimock.Equal(*mm_want_ptrs.thingID, mm_got.thingID) {
+				mmDeleteByThingID.t.Errorf("ThingTagRepositoryMock.DeleteByThingID got unexpected parameter thingID, want: %#v, got: %#v%s\n", *mm_want_ptrs.thingID, mm_got.thingID, minimock.Diff(*mm_want_ptrs.thingID, mm_got.thingID))
+			}
+
+			if mm_want_ptrs.tx != nil && !minimock.Equal(*mm_want_ptrs.tx, mm_got.tx) {
+				mmDeleteByThingID.t.Errorf("ThingTagRepositoryMock.DeleteByThingID got unexpected parameter tx, want: %#v, got: %#v%s\n", *mm_want_ptrs.tx, mm_got.tx, minimock.Diff(*mm_want_ptrs.tx, mm_got.tx))
+			}
+
+		} else if mm_want != nil && !minimock.Equal(*mm_want, mm_got) {
+			mmDeleteByThingID.t.Errorf("ThingTagRepositoryMock.DeleteByThingID got unexpected parameters, want: %#v, got: %#v%s\n", *mm_want, mm_got, minimock.Diff(*mm_want, mm_got))
+		}
+
+		mm_results := mmDeleteByThingID.DeleteByThingIDMock.defaultExpectation.results
+		if mm_results == nil {
+			mmDeleteByThingID.t.Fatal("No results are set for the ThingTagRepositoryMock.DeleteByThingID")
+		}
+		return (*mm_results).err
+	}
+	if mmDeleteByThingID.funcDeleteByThingID != nil {
+		return mmDeleteByThingID.funcDeleteByThingID(ctx, thingID, tx)
+	}
+	mmDeleteByThingID.t.Fatalf("Unexpected call to ThingTagRepositoryMock.DeleteByThingID. %v %v %v", ctx, thingID, tx)
+	return
+}
+
+// DeleteByThingIDAfterCounter returns a count of finished ThingTagRepositoryMock.DeleteByThingID invocations
+func (mmDeleteByThingID *ThingTagRepositoryMock) DeleteByThingIDAfterCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmDeleteByThingID.afterDeleteByThingIDCounter)
+}
+
+// DeleteByThingIDBeforeCounter returns a count of ThingTagRepositoryMock.DeleteByThingID invocations
+func (mmDeleteByThingID *ThingTagRepositoryMock) DeleteByThingIDBeforeCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmDeleteByThingID.beforeDeleteByThingIDCounter)
+}
+
+// Calls returns a list of arguments used in each call to ThingTagRepositoryMock.DeleteByThingID.
+// The list is in the same order as the calls were made (i.e. recent calls have a higher index)
+func (mmDeleteByThingID *mThingTagRepositoryMockDeleteByThingID) Calls() []*ThingTagRepositoryMockDeleteByThingIDParams {
+	mmDeleteByThingID.mutex.RLock()
+
+	argCopy := make([]*ThingTagRepositoryMockDeleteByThingIDParams, len(mmDeleteByThingID.callArgs))
+	copy(argCopy, mmDeleteByThingID.callArgs)
+
+	mmDeleteByThingID.mutex.RUnlock()
+
+	return argCopy
+}
+
+// MinimockDeleteByThingIDDone returns true if the count of the DeleteByThingID invocations corresponds
+// the number of defined expectations
+func (m *ThingTagRepositoryMock) MinimockDeleteByThingIDDone() bool {
+	if m.DeleteByThingIDMock.optional {
+		// Optional methods provide '0 or more' call count restriction.
+		return true
+	}
+
+	for _, e := range m.DeleteByThingIDMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			return false
+		}
+	}
+
+	return m.DeleteByThingIDMock.invocationsDone()
+}
+
+// MinimockDeleteByThingIDInspect logs each unmet expectation
+func (m *ThingTagRepositoryMock) MinimockDeleteByThingIDInspect() {
+	for _, e := range m.DeleteByThingIDMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			m.t.Errorf("Expected call to ThingTagRepositoryMock.DeleteByThingID with params: %#v", *e.params)
+		}
+	}
+
+	afterDeleteByThingIDCounter := mm_atomic.LoadUint64(&m.afterDeleteByThingIDCounter)
+	// if default expectation was set then invocations count should be greater than zero
+	if m.DeleteByThingIDMock.defaultExpectation != nil && afterDeleteByThingIDCounter < 1 {
+		if m.DeleteByThingIDMock.defaultExpectation.params == nil {
+			m.t.Error("Expected call to ThingTagRepositoryMock.DeleteByThingID")
+		} else {
+			m.t.Errorf("Expected call to ThingTagRepositoryMock.DeleteByThingID with params: %#v", *m.DeleteByThingIDMock.defaultExpectation.params)
+		}
+	}
+	// if func was set then invocations count should be greater than zero
+	if m.funcDeleteByThingID != nil && afterDeleteByThingIDCounter < 1 {
+		m.t.Error("Expected call to ThingTagRepositoryMock.DeleteByThingID")
+	}
+
+	if !m.DeleteByThingIDMock.invocationsDone() && afterDeleteByThingIDCounter > 0 {
+		m.t.Errorf("Expected %d calls to ThingTagRepositoryMock.DeleteByThingID but found %d calls",
+			mm_atomic.LoadUint64(&m.DeleteByThingIDMock.expectedInvocations), afterDeleteByThingIDCounter)
+	}
+}
+
+// MinimockFinish checks that all mocked methods have been called the expected number of times
+func (m *ThingTagRepositoryMock) MinimockFinish() {
+	m.finishOnce.Do(func() {
+		if !m.minimockDone() {
+			m.MinimockDeleteByThingIDInspect()
+		}
+	})
+}
+
+// MinimockWait waits for all mocked methods to be called the expected number of times
+func (m *ThingTagRepositoryMock) MinimockWait(timeout mm_time.Duration) {
+	timeoutCh := mm_time.After(timeout)
+	for {
+		if m.minimockDone() {
+			return
+		}
+		select {
+		case <-timeoutCh:
+			m.MinimockFinish()
+			return
+		case <-mm_time.After(10 * mm_time.Millisecond):
+		}
+	}
+}
+
+func (m *ThingTagRepositoryMock) minimockDone() bool {
+	done := true
+	return done &&
+		m.MinimockDeleteByThingIDDone()
+}

+ 7 - 7
internal/api/v1/place/update_place.go

@@ -1,13 +1,13 @@
 package place
 
 import (
+	"github.com/go-playground/validator/v10"
+	"github.com/gofiber/fiber/v2"
+
 	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/factory"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/mappers"
-	"github.com/go-playground/validator/v10"
-	"github.com/gofiber/fiber/v2"
 )
 
 // @Router 		/api/v1/places/{placeId} [put]
@@ -21,7 +21,7 @@ import (
 // @security 	APIKey
 // @Accept      json
 // @Produce     json
-func UpdatePlaceHandler(sp interfaces.ServiceProvider) fiber.Handler {
+func UpdatePlaceHandler(placeRepository PlaceRepository) fiber.Handler {
 	return func(fctx *fiber.Ctx) error {
 		ctx := fctx.Context()
 		id, err := fctx.ParamsInt("placeId")
@@ -39,18 +39,18 @@ func UpdatePlaceHandler(sp interfaces.ServiceProvider) fiber.Handler {
 			return fctx.Status(fiber.StatusBadRequest).JSON(factory.CreateValidateErrorResponse(err))
 		}
 
-		err = sp.GetPlaceRepository().Update(ctx, mappers.ConvertToUpdatePlaceRequestModel(id, req), nil)
+		err = placeRepository.Update(ctx, mappers.ToUpdatePlaceRequest(id, req), nil)
 		if err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
-		res, err := sp.GetPlaceRepository().Get(ctx, id)
+		res, err := placeRepository.Get(ctx, id)
 		if err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
 		res = helpers.ApplyLocation(fctx, res)
 
-		return fctx.JSON(mappers.ConvertToPlaceResponseDTO(*res))
+		return fctx.JSON(mappers.ToPlaceResponse(*res))
 	}
 }

+ 26 - 25
internal/api/v1/place/update_place_test.go

@@ -8,20 +8,21 @@ import (
 	"strconv"
 	"testing"
 
-	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
-	repoMocks "git.dmitriygnatenko.ru/dima/homethings/internal/repositories/mocks"
-	sp "git.dmitriygnatenko.ru/dima/homethings/internal/service_provider"
 	"github.com/brianvoe/gofakeit/v6"
 	"github.com/gofiber/fiber/v2"
 	"github.com/gojuno/minimock/v3"
 	"github.com/stretchr/testify/assert"
+
+	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/place/mocks"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
 )
 
-func Test_UpdatePlaceHandler(t *testing.T) {
+func TestUpdatePlaceHandler(t *testing.T) {
+	t.Parallel()
+
 	type req struct {
 		method      string
 		route       string
@@ -30,7 +31,6 @@ func Test_UpdatePlaceHandler(t *testing.T) {
 	}
 
 	var (
-		mc        = minimock.NewController(t)
 		placeID   = gofakeit.Number(1, 1000)
 		parentID  = gofakeit.Number(1, 1000)
 		title     = gofakeit.Phrase()
@@ -69,15 +69,15 @@ func Test_UpdatePlaceHandler(t *testing.T) {
 		req           req
 		resCode       int
 		resBody       interface{}
-		placeRepoMock func(mc *minimock.Controller) interfaces.PlaceRepository
+		placeRepoMock func(mc *minimock.Controller) PlaceRepository
 	}{
 		{
 			name:    "positive case",
 			req:     correctReq,
 			resCode: fiber.StatusOK,
 			resBody: expectedRes,
-			placeRepoMock: func(mc *minimock.Controller) interfaces.PlaceRepository {
-				mock := repoMocks.NewPlaceRepositoryMock(mc)
+			placeRepoMock: func(mc *minimock.Controller) PlaceRepository {
+				mock := mocks.NewPlaceRepositoryMock(mc)
 
 				mock.UpdateMock.Inspect(func(ctx context.Context, req models.UpdatePlaceRequest, tx *sql.Tx) {
 					assert.Equal(mc, title, req.Title)
@@ -98,8 +98,8 @@ func Test_UpdatePlaceHandler(t *testing.T) {
 				route:  "/v1/places/" + gofakeit.Word(),
 			},
 			resCode: fiber.StatusBadRequest,
-			placeRepoMock: func(mc *minimock.Controller) interfaces.PlaceRepository {
-				return repoMocks.NewPlaceRepositoryMock(mc)
+			placeRepoMock: func(mc *minimock.Controller) PlaceRepository {
+				return mocks.NewPlaceRepositoryMock(mc)
 			},
 		},
 		{
@@ -109,8 +109,8 @@ func Test_UpdatePlaceHandler(t *testing.T) {
 				route:  "/v1/places/" + strconv.Itoa(placeID),
 			},
 			resCode: fiber.StatusBadRequest,
-			placeRepoMock: func(mc *minimock.Controller) interfaces.PlaceRepository {
-				return repoMocks.NewPlaceRepositoryMock(mc)
+			placeRepoMock: func(mc *minimock.Controller) PlaceRepository {
+				return mocks.NewPlaceRepositoryMock(mc)
 			},
 		},
 		{
@@ -128,16 +128,16 @@ func Test_UpdatePlaceHandler(t *testing.T) {
 					Tag:   "required",
 				},
 			},
-			placeRepoMock: func(mc *minimock.Controller) interfaces.PlaceRepository {
-				return repoMocks.NewPlaceRepositoryMock(mc)
+			placeRepoMock: func(mc *minimock.Controller) PlaceRepository {
+				return mocks.NewPlaceRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - repository error (update place)",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			placeRepoMock: func(mc *minimock.Controller) interfaces.PlaceRepository {
-				mock := repoMocks.NewPlaceRepositoryMock(mc)
+			placeRepoMock: func(mc *minimock.Controller) PlaceRepository {
+				mock := mocks.NewPlaceRepositoryMock(mc)
 
 				mock.UpdateMock.Inspect(func(ctx context.Context, req models.UpdatePlaceRequest, tx *sql.Tx) {
 					assert.Equal(mc, title, req.Title)
@@ -151,8 +151,8 @@ func Test_UpdatePlaceHandler(t *testing.T) {
 			name:    "negative case - repository error (get place)",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			placeRepoMock: func(mc *minimock.Controller) interfaces.PlaceRepository {
-				mock := repoMocks.NewPlaceRepositoryMock(mc)
+			placeRepoMock: func(mc *minimock.Controller) PlaceRepository {
+				mock := mocks.NewPlaceRepositoryMock(mc)
 
 				mock.UpdateMock.Inspect(func(ctx context.Context, req models.UpdatePlaceRequest, tx *sql.Tx) {
 					assert.Equal(mc, title, req.Title)
@@ -170,10 +170,11 @@ func Test_UpdatePlaceHandler(t *testing.T) {
 
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			fiberApp := fiber.New()
-			serviceProvider := sp.InitMock(tt.placeRepoMock(mc))
+			t.Parallel()
 
-			fiberApp.Put("/v1/places/:placeId", UpdatePlaceHandler(serviceProvider))
+			mc := minimock.NewController(t)
+			fiberApp := fiber.New()
+			fiberApp.Put("/v1/places/:placeId", UpdatePlaceHandler(tt.placeRepoMock(mc)))
 
 			fiberReq := httptest.NewRequest(tt.req.method, tt.req.route, helpers.ConvertDataToIOReader(tt.req.body))
 			fiberReq.Header.Add(fiber.HeaderContentType, tt.req.contentType)

+ 38 - 7
internal/api/v1/tag/add_tag.go

@@ -1,13 +1,44 @@
 package tag
 
+//go:generate mkdir -p mocks
+//go:generate rm -rf ./mocks/*_minimock.go
+//go:generate minimock -i TagRepository,ThingRepository,ThingTagRepository -o ./mocks/ -s "_minimock.go"
+
 import (
+	"context"
+	"database/sql"
+
+	"github.com/go-playground/validator/v10"
+	"github.com/gofiber/fiber/v2"
+
 	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/factory"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/mappers"
-	"github.com/go-playground/validator/v10"
-	"github.com/gofiber/fiber/v2"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
+)
+
+type (
+	TagRepository interface {
+		GetAll(ctx context.Context) ([]models.Tag, error)
+		Get(ctx context.Context, tagID int) (*models.Tag, error)
+		GetByThingID(ctx context.Context, thingID int) ([]models.Tag, error)
+		Add(ctx context.Context, req models.AddTagRequest, tx *sql.Tx) (int, error)
+		Update(ctx context.Context, req models.UpdateTagRequest, tx *sql.Tx) error
+		Delete(ctx context.Context, tagID int, tx *sql.Tx) error
+		BeginTx(ctx context.Context, level sql.IsolationLevel) (*sql.Tx, error)
+		CommitTx(tx *sql.Tx) error
+	}
+
+	ThingRepository interface {
+		Get(ctx context.Context, thingID int) (*models.Thing, error)
+	}
+
+	ThingTagRepository interface {
+		Add(ctx context.Context, req models.AddThingTagRequest, tx *sql.Tx) error
+		Delete(ctx context.Context, req models.DeleteThingTagRequest, tx *sql.Tx) error
+		DeleteByTagID(ctx context.Context, tagID int, tx *sql.Tx) error
+	}
 )
 
 // @Router 		/api/v1/tags [post]
@@ -20,7 +51,7 @@ import (
 // @security 	APIKey
 // @Accept      json
 // @Produce     json
-func AddTagHandler(sp interfaces.ServiceProvider) fiber.Handler {
+func AddTagHandler(tagRepository TagRepository) fiber.Handler {
 	return func(fctx *fiber.Ctx) error {
 		ctx := fctx.Context()
 		req := dto.AddTagRequest{}
@@ -33,18 +64,18 @@ func AddTagHandler(sp interfaces.ServiceProvider) fiber.Handler {
 			return fctx.Status(fiber.StatusBadRequest).JSON(factory.CreateValidateErrorResponse(err))
 		}
 
-		id, err := sp.GetTagRepository().Add(ctx, mappers.ConvertToAddTagRequestModel(req), nil)
+		id, err := tagRepository.Add(ctx, mappers.ToAddTagRequest(req), nil)
 		if err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
-		res, err := sp.GetTagRepository().Get(ctx, id)
+		res, err := tagRepository.Get(ctx, id)
 		if err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
 		res = helpers.ApplyLocation(fctx, res)
 
-		return fctx.JSON(mappers.ConvertToTagResponseDTO(*res))
+		return fctx.JSON(mappers.ToTagResponse(*res))
 	}
 }

+ 26 - 25
internal/api/v1/tag/add_tag_test.go

@@ -7,20 +7,21 @@ import (
 	"net/http/httptest"
 	"testing"
 
-	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
-	repoMocks "git.dmitriygnatenko.ru/dima/homethings/internal/repositories/mocks"
-	sp "git.dmitriygnatenko.ru/dima/homethings/internal/service_provider"
 	"github.com/brianvoe/gofakeit/v6"
 	"github.com/gofiber/fiber/v2"
 	"github.com/gojuno/minimock/v3"
 	"github.com/stretchr/testify/assert"
+
+	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/tag/mocks"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
 )
 
-func Test_AddTagHandler(t *testing.T) {
+func TestAddTagHandler(t *testing.T) {
+	t.Parallel()
+
 	type req struct {
 		method      string
 		route       string
@@ -29,7 +30,6 @@ func Test_AddTagHandler(t *testing.T) {
 	}
 
 	var (
-		mc        = minimock.NewController(t)
 		tagID     = gofakeit.Number(1, 1000)
 		title     = gofakeit.Phrase()
 		style     = gofakeit.Phrase()
@@ -68,15 +68,15 @@ func Test_AddTagHandler(t *testing.T) {
 		req         req
 		resCode     int
 		resBody     interface{}
-		tagRepoMock func(mc *minimock.Controller) interfaces.TagRepository
+		tagRepoMock func(mc *minimock.Controller) TagRepository
 	}{
 		{
 			name:    "positive case",
 			req:     correctReq,
 			resCode: fiber.StatusOK,
 			resBody: expectedRes,
-			tagRepoMock: func(mc *minimock.Controller) interfaces.TagRepository {
-				mock := repoMocks.NewTagRepositoryMock(mc)
+			tagRepoMock: func(mc *minimock.Controller) TagRepository {
+				mock := mocks.NewTagRepositoryMock(mc)
 
 				mock.AddMock.Inspect(func(ctx context.Context, req models.AddTagRequest, tx *sql.Tx) {
 					assert.Equal(mc, title, req.Title)
@@ -97,8 +97,8 @@ func Test_AddTagHandler(t *testing.T) {
 				route:  "/v1/tags/",
 			},
 			resCode: fiber.StatusBadRequest,
-			tagRepoMock: func(mc *minimock.Controller) interfaces.TagRepository {
-				return repoMocks.NewTagRepositoryMock(mc)
+			tagRepoMock: func(mc *minimock.Controller) TagRepository {
+				return mocks.NewTagRepositoryMock(mc)
 			},
 		},
 		{
@@ -118,8 +118,8 @@ func Test_AddTagHandler(t *testing.T) {
 					Tag:   "required",
 				},
 			},
-			tagRepoMock: func(mc *minimock.Controller) interfaces.TagRepository {
-				return repoMocks.NewTagRepositoryMock(mc)
+			tagRepoMock: func(mc *minimock.Controller) TagRepository {
+				return mocks.NewTagRepositoryMock(mc)
 			},
 		},
 		{
@@ -139,16 +139,16 @@ func Test_AddTagHandler(t *testing.T) {
 					Tag:   "required",
 				},
 			},
-			tagRepoMock: func(mc *minimock.Controller) interfaces.TagRepository {
-				return repoMocks.NewTagRepositoryMock(mc)
+			tagRepoMock: func(mc *minimock.Controller) TagRepository {
+				return mocks.NewTagRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - repository error (add)",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			tagRepoMock: func(mc *minimock.Controller) interfaces.TagRepository {
-				mock := repoMocks.NewTagRepositoryMock(mc)
+			tagRepoMock: func(mc *minimock.Controller) TagRepository {
+				mock := mocks.NewTagRepositoryMock(mc)
 
 				mock.AddMock.Inspect(func(ctx context.Context, req models.AddTagRequest, tx *sql.Tx) {
 					assert.Equal(mc, title, req.Title)
@@ -162,8 +162,8 @@ func Test_AddTagHandler(t *testing.T) {
 			name:    "negative case - repository error (get)",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			tagRepoMock: func(mc *minimock.Controller) interfaces.TagRepository {
-				mock := repoMocks.NewTagRepositoryMock(mc)
+			tagRepoMock: func(mc *minimock.Controller) TagRepository {
+				mock := mocks.NewTagRepositoryMock(mc)
 
 				mock.AddMock.Inspect(func(ctx context.Context, req models.AddTagRequest, tx *sql.Tx) {
 					assert.Equal(mc, title, req.Title)
@@ -181,10 +181,11 @@ func Test_AddTagHandler(t *testing.T) {
 
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			fiberApp := fiber.New()
-			serviceProvider := sp.InitMock(tt.tagRepoMock(mc))
+			t.Parallel()
 
-			fiberApp.Post("/v1/tags", AddTagHandler(serviceProvider))
+			mc := minimock.NewController(t)
+			fiberApp := fiber.New()
+			fiberApp.Post("/v1/tags", AddTagHandler(tt.tagRepoMock(mc)))
 
 			fiberReq := httptest.NewRequest(tt.req.method, tt.req.route, helpers.ConvertDataToIOReader(tt.req.body))
 			fiberReq.Header.Add(fiber.HeaderContentType, tt.req.contentType)

+ 13 - 8
internal/api/v1/tag/add_thing_tag.go

@@ -2,11 +2,12 @@ package tag
 
 import (
 	"database/sql"
+	"errors"
+
+	"github.com/gofiber/fiber/v2"
 
 	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/mappers"
-	"github.com/gofiber/fiber/v2"
 )
 
 // @Router 		/api/v1/tags/{tagId}/thing/{thingId} [post]
@@ -20,7 +21,11 @@ import (
 // @security 	APIKey
 // @Accept      json
 // @Produce     json
-func AddThingTagHandler(sp interfaces.ServiceProvider) fiber.Handler {
+func AddThingTagHandler(
+	tagRepository TagRepository,
+	thingRepository ThingRepository,
+	thingTagRepository ThingTagRepository,
+) fiber.Handler {
 	return func(fctx *fiber.Ctx) error {
 		ctx := fctx.Context()
 		tagID, err := fctx.ParamsInt("tagId")
@@ -33,27 +38,27 @@ func AddThingTagHandler(sp interfaces.ServiceProvider) fiber.Handler {
 			return fiber.NewError(fiber.StatusBadRequest, err.Error())
 		}
 
-		tag, err := sp.GetTagRepository().Get(ctx, tagID)
+		tag, err := tagRepository.Get(ctx, tagID)
 		if err != nil {
-			if err == sql.ErrNoRows {
+			if errors.Is(err, sql.ErrNoRows) {
 				return fiber.NewError(fiber.StatusBadRequest, "")
 			}
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
-		if _, err = sp.GetThingRepository().Get(ctx, thingID); err != nil {
+		if _, err = thingRepository.Get(ctx, thingID); err != nil {
 			if err == sql.ErrNoRows {
 				return fiber.NewError(fiber.StatusBadRequest, "")
 			}
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
-		if err = sp.GetThingTagRepository().Add(ctx, mappers.ConvertToAddThingTagRequestModel(tagID, thingID), nil); err != nil {
+		if err = thingTagRepository.Add(ctx, mappers.ToAddThingTagRequest(tagID, thingID), nil); err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
 		tag = helpers.ApplyLocation(fctx, tag)
 
-		return fctx.JSON(mappers.ConvertToTagResponseDTO(*tag))
+		return fctx.JSON(mappers.ToTagResponse(*tag))
 	}
 }

+ 68 - 62
internal/api/v1/tag/add_thing_tag_test.go

@@ -8,20 +8,21 @@ import (
 	"strconv"
 	"testing"
 
-	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
-	repoMocks "git.dmitriygnatenko.ru/dima/homethings/internal/repositories/mocks"
-	sp "git.dmitriygnatenko.ru/dima/homethings/internal/service_provider"
 	"github.com/brianvoe/gofakeit/v6"
 	"github.com/gofiber/fiber/v2"
 	"github.com/gojuno/minimock/v3"
 	"github.com/stretchr/testify/assert"
+
+	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/tag/mocks"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
 )
 
-func Test_AddThingTagHandler(t *testing.T) {
+func TestAddThingTagHandler(t *testing.T) {
+	t.Parallel()
+
 	type req struct {
 		method      string
 		route       string
@@ -29,7 +30,6 @@ func Test_AddThingTagHandler(t *testing.T) {
 	}
 
 	var (
-		mc        = minimock.NewController(t)
 		tagID     = gofakeit.Number(1, 1000)
 		thingID   = gofakeit.Number(1, 1000)
 		testError = errors.New(gofakeit.Phrase())
@@ -63,17 +63,17 @@ func Test_AddThingTagHandler(t *testing.T) {
 		req              req
 		resCode          int
 		resBody          interface{}
-		tagRepoMock      func(mc *minimock.Controller) interfaces.TagRepository
-		thingRepoMock    func(mc *minimock.Controller) interfaces.ThingRepository
-		thingTagRepoMock func(mc *minimock.Controller) interfaces.ThingTagRepository
+		tagRepoMock      func(mc *minimock.Controller) TagRepository
+		thingRepoMock    func(mc *minimock.Controller) ThingRepository
+		thingTagRepoMock func(mc *minimock.Controller) ThingTagRepository
 	}{
 		{
 			name:    "positive case",
 			req:     correctReq,
 			resCode: fiber.StatusOK,
 			resBody: expectedRes,
-			tagRepoMock: func(mc *minimock.Controller) interfaces.TagRepository {
-				mock := repoMocks.NewTagRepositoryMock(mc)
+			tagRepoMock: func(mc *minimock.Controller) TagRepository {
+				mock := mocks.NewTagRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, tagID, id)
@@ -81,8 +81,8 @@ func Test_AddThingTagHandler(t *testing.T) {
 
 				return mock
 			},
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				mock := repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				mock := mocks.NewThingRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -90,8 +90,8 @@ func Test_AddThingTagHandler(t *testing.T) {
 
 				return mock
 			},
-			thingTagRepoMock: func(mc *minimock.Controller) interfaces.ThingTagRepository {
-				mock := repoMocks.NewThingTagRepositoryMock(mc)
+			thingTagRepoMock: func(mc *minimock.Controller) ThingTagRepository {
+				mock := mocks.NewThingTagRepositoryMock(mc)
 
 				mock.AddMock.Inspect(func(ctx context.Context, req models.AddThingTagRequest, tx *sql.Tx) {
 					assert.Equal(mc, tagID, req.TagID)
@@ -109,14 +109,14 @@ func Test_AddThingTagHandler(t *testing.T) {
 				contentType: fiber.MIMEApplicationJSON,
 			},
 			resCode: fiber.StatusBadRequest,
-			tagRepoMock: func(mc *minimock.Controller) interfaces.TagRepository {
-				return repoMocks.NewTagRepositoryMock(mc)
+			tagRepoMock: func(mc *minimock.Controller) TagRepository {
+				return mocks.NewTagRepositoryMock(mc)
 			},
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				return repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				return mocks.NewThingRepositoryMock(mc)
 			},
-			thingTagRepoMock: func(mc *minimock.Controller) interfaces.ThingTagRepository {
-				return repoMocks.NewThingTagRepositoryMock(mc)
+			thingTagRepoMock: func(mc *minimock.Controller) ThingTagRepository {
+				return mocks.NewThingTagRepositoryMock(mc)
 			},
 		},
 		{
@@ -127,22 +127,22 @@ func Test_AddThingTagHandler(t *testing.T) {
 				contentType: fiber.MIMEApplicationJSON,
 			},
 			resCode: fiber.StatusBadRequest,
-			tagRepoMock: func(mc *minimock.Controller) interfaces.TagRepository {
-				return repoMocks.NewTagRepositoryMock(mc)
+			tagRepoMock: func(mc *minimock.Controller) TagRepository {
+				return mocks.NewTagRepositoryMock(mc)
 			},
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				return repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				return mocks.NewThingRepositoryMock(mc)
 			},
-			thingTagRepoMock: func(mc *minimock.Controller) interfaces.ThingTagRepository {
-				return repoMocks.NewThingTagRepositoryMock(mc)
+			thingTagRepoMock: func(mc *minimock.Controller) ThingTagRepository {
+				return mocks.NewThingTagRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - tag is not exist",
 			req:     correctReq,
 			resCode: fiber.StatusBadRequest,
-			tagRepoMock: func(mc *minimock.Controller) interfaces.TagRepository {
-				mock := repoMocks.NewTagRepositoryMock(mc)
+			tagRepoMock: func(mc *minimock.Controller) TagRepository {
+				mock := mocks.NewTagRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, tagID, id)
@@ -150,19 +150,19 @@ func Test_AddThingTagHandler(t *testing.T) {
 
 				return mock
 			},
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				return repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				return mocks.NewThingRepositoryMock(mc)
 			},
-			thingTagRepoMock: func(mc *minimock.Controller) interfaces.ThingTagRepository {
-				return repoMocks.NewThingTagRepositoryMock(mc)
+			thingTagRepoMock: func(mc *minimock.Controller) ThingTagRepository {
+				return mocks.NewThingTagRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - tag repository error",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			tagRepoMock: func(mc *minimock.Controller) interfaces.TagRepository {
-				mock := repoMocks.NewTagRepositoryMock(mc)
+			tagRepoMock: func(mc *minimock.Controller) TagRepository {
+				mock := mocks.NewTagRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, tagID, id)
@@ -170,19 +170,19 @@ func Test_AddThingTagHandler(t *testing.T) {
 
 				return mock
 			},
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				return repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				return mocks.NewThingRepositoryMock(mc)
 			},
-			thingTagRepoMock: func(mc *minimock.Controller) interfaces.ThingTagRepository {
-				return repoMocks.NewThingTagRepositoryMock(mc)
+			thingTagRepoMock: func(mc *minimock.Controller) ThingTagRepository {
+				return mocks.NewThingTagRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - thing is not exist",
 			req:     correctReq,
 			resCode: fiber.StatusBadRequest,
-			tagRepoMock: func(mc *minimock.Controller) interfaces.TagRepository {
-				mock := repoMocks.NewTagRepositoryMock(mc)
+			tagRepoMock: func(mc *minimock.Controller) TagRepository {
+				mock := mocks.NewTagRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, tagID, id)
@@ -190,8 +190,8 @@ func Test_AddThingTagHandler(t *testing.T) {
 
 				return mock
 			},
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				mock := repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				mock := mocks.NewThingRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -199,16 +199,16 @@ func Test_AddThingTagHandler(t *testing.T) {
 
 				return mock
 			},
-			thingTagRepoMock: func(mc *minimock.Controller) interfaces.ThingTagRepository {
-				return repoMocks.NewThingTagRepositoryMock(mc)
+			thingTagRepoMock: func(mc *minimock.Controller) ThingTagRepository {
+				return mocks.NewThingTagRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - thing repository error",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			tagRepoMock: func(mc *minimock.Controller) interfaces.TagRepository {
-				mock := repoMocks.NewTagRepositoryMock(mc)
+			tagRepoMock: func(mc *minimock.Controller) TagRepository {
+				mock := mocks.NewTagRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, tagID, id)
@@ -216,8 +216,8 @@ func Test_AddThingTagHandler(t *testing.T) {
 
 				return mock
 			},
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				mock := repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				mock := mocks.NewThingRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -225,16 +225,16 @@ func Test_AddThingTagHandler(t *testing.T) {
 
 				return mock
 			},
-			thingTagRepoMock: func(mc *minimock.Controller) interfaces.ThingTagRepository {
-				return repoMocks.NewThingTagRepositoryMock(mc)
+			thingTagRepoMock: func(mc *minimock.Controller) ThingTagRepository {
+				return mocks.NewThingTagRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - thing tag repository error",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			tagRepoMock: func(mc *minimock.Controller) interfaces.TagRepository {
-				mock := repoMocks.NewTagRepositoryMock(mc)
+			tagRepoMock: func(mc *minimock.Controller) TagRepository {
+				mock := mocks.NewTagRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, tagID, id)
@@ -242,8 +242,8 @@ func Test_AddThingTagHandler(t *testing.T) {
 
 				return mock
 			},
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				mock := repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				mock := mocks.NewThingRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -251,8 +251,8 @@ func Test_AddThingTagHandler(t *testing.T) {
 
 				return mock
 			},
-			thingTagRepoMock: func(mc *minimock.Controller) interfaces.ThingTagRepository {
-				mock := repoMocks.NewThingTagRepositoryMock(mc)
+			thingTagRepoMock: func(mc *minimock.Controller) ThingTagRepository {
+				mock := mocks.NewThingTagRepositoryMock(mc)
 
 				mock.AddMock.Inspect(func(ctx context.Context, req models.AddThingTagRequest, tx *sql.Tx) {
 					assert.Equal(mc, tagID, req.TagID)
@@ -266,10 +266,16 @@ func Test_AddThingTagHandler(t *testing.T) {
 
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
+			t.Parallel()
+
+			mc := minimock.NewController(t)
 			fiberApp := fiber.New()
-			serviceProvider := sp.InitMock(tt.tagRepoMock(mc), tt.thingRepoMock(mc), tt.thingTagRepoMock(mc))
 
-			fiberApp.Post("/v1/tags/:tagId/thing/:thingId", AddThingTagHandler(serviceProvider))
+			fiberApp.Post("/v1/tags/:tagId/thing/:thingId", AddThingTagHandler(
+				tt.tagRepoMock(mc),
+				tt.thingRepoMock(mc),
+				tt.thingTagRepoMock(mc),
+			))
 
 			fiberReq := httptest.NewRequest(tt.req.method, tt.req.route, nil)
 			fiberReq.Header.Add(fiber.HeaderContentType, tt.req.contentType)

+ 13 - 9
internal/api/v1/tag/delete_tag.go

@@ -2,11 +2,12 @@ package tag
 
 import (
 	"database/sql"
+	"errors"
+
+	"github.com/gofiber/fiber/v2"
 
 	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/factory"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
-	"github.com/gofiber/fiber/v2"
 )
 
 // @Router 		/api/v1/tags/{tagId} [delete]
@@ -19,7 +20,10 @@ import (
 // @security 	APIKey
 // @Accept      json
 // @Produce     json
-func DeleteTagHandler(sp interfaces.ServiceProvider) fiber.Handler {
+func DeleteTagHandler(
+	tagRepository TagRepository,
+	thingTagRepository ThingTagRepository,
+) fiber.Handler {
 	return func(fctx *fiber.Ctx) error {
 		ctx := fctx.Context()
 		id, err := fctx.ParamsInt("tagId")
@@ -27,27 +31,27 @@ func DeleteTagHandler(sp interfaces.ServiceProvider) fiber.Handler {
 			return fiber.NewError(fiber.StatusBadRequest, err.Error())
 		}
 
-		if _, err = sp.GetTagRepository().Get(ctx, id); err != nil {
-			if err == sql.ErrNoRows {
+		if _, err = tagRepository.Get(ctx, id); err != nil {
+			if errors.Is(err, sql.ErrNoRows) {
 				return fiber.NewError(fiber.StatusBadRequest, "")
 			}
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
-		tx, err := sp.GetTagRepository().BeginTx(ctx, API.DefaultTxLevel)
+		tx, err := tagRepository.BeginTx(ctx, API.DefaultTxLevel)
 		if err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
-		if err = sp.GetThingTagRepository().DeleteByTagID(ctx, id, tx); err != nil {
+		if err = thingTagRepository.DeleteByTagID(ctx, id, tx); err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
-		if err = sp.GetTagRepository().Delete(ctx, id, tx); err != nil {
+		if err = tagRepository.Delete(ctx, id, tx); err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
-		if err = sp.GetTagRepository().CommitTx(tx); err != nil {
+		if err = tagRepository.CommitTx(tx); err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 

+ 46 - 45
internal/api/v1/tag/delete_tag_test.go

@@ -8,19 +8,20 @@ import (
 	"strconv"
 	"testing"
 
-	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
-	repoMocks "git.dmitriygnatenko.ru/dima/homethings/internal/repositories/mocks"
-	sp "git.dmitriygnatenko.ru/dima/homethings/internal/service_provider"
 	"github.com/brianvoe/gofakeit/v6"
 	"github.com/gofiber/fiber/v2"
 	"github.com/gojuno/minimock/v3"
 	"github.com/stretchr/testify/assert"
+
+	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/tag/mocks"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
 )
 
-func Test_DeleteTagHandler(t *testing.T) {
+func TestDeleteTagHandler(t *testing.T) {
+	t.Parallel()
+
 	type req struct {
 		method      string
 		route       string
@@ -28,7 +29,6 @@ func Test_DeleteTagHandler(t *testing.T) {
 	}
 
 	var (
-		mc        = minimock.NewController(t)
 		tagID     = gofakeit.Number(1, 1000)
 		testError = errors.New(gofakeit.Phrase())
 
@@ -44,8 +44,8 @@ func Test_DeleteTagHandler(t *testing.T) {
 		req              req
 		resCode          int
 		resBody          interface{}
-		tagRepoMock      func(mc *minimock.Controller) interfaces.TagRepository
-		thingTagRepoMock func(mc *minimock.Controller) interfaces.ThingTagRepository
+		tagRepoMock      func(mc *minimock.Controller) TagRepository
+		thingTagRepoMock func(mc *minimock.Controller) ThingTagRepository
 	}{
 		{
 			name: "negative case - bad request",
@@ -55,19 +55,19 @@ func Test_DeleteTagHandler(t *testing.T) {
 				contentType: fiber.MIMEApplicationJSON,
 			},
 			resCode: fiber.StatusBadRequest,
-			tagRepoMock: func(mc *minimock.Controller) interfaces.TagRepository {
-				return repoMocks.NewTagRepositoryMock(mc)
+			tagRepoMock: func(mc *minimock.Controller) TagRepository {
+				return mocks.NewTagRepositoryMock(mc)
 			},
-			thingTagRepoMock: func(mc *minimock.Controller) interfaces.ThingTagRepository {
-				return repoMocks.NewThingTagRepositoryMock(mc)
+			thingTagRepoMock: func(mc *minimock.Controller) ThingTagRepository {
+				return mocks.NewThingTagRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - tag is not exist",
 			req:     correctReq,
 			resCode: fiber.StatusBadRequest,
-			tagRepoMock: func(mc *minimock.Controller) interfaces.TagRepository {
-				mock := repoMocks.NewTagRepositoryMock(mc)
+			tagRepoMock: func(mc *minimock.Controller) TagRepository {
+				mock := mocks.NewTagRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, tagID, id)
@@ -75,16 +75,16 @@ func Test_DeleteTagHandler(t *testing.T) {
 
 				return mock
 			},
-			thingTagRepoMock: func(mc *minimock.Controller) interfaces.ThingTagRepository {
-				return repoMocks.NewThingTagRepositoryMock(mc)
+			thingTagRepoMock: func(mc *minimock.Controller) ThingTagRepository {
+				return mocks.NewThingTagRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - tag repository error (get)",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			tagRepoMock: func(mc *minimock.Controller) interfaces.TagRepository {
-				mock := repoMocks.NewTagRepositoryMock(mc)
+			tagRepoMock: func(mc *minimock.Controller) TagRepository {
+				mock := mocks.NewTagRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, tagID, id)
@@ -92,16 +92,16 @@ func Test_DeleteTagHandler(t *testing.T) {
 
 				return mock
 			},
-			thingTagRepoMock: func(mc *minimock.Controller) interfaces.ThingTagRepository {
-				return repoMocks.NewThingTagRepositoryMock(mc)
+			thingTagRepoMock: func(mc *minimock.Controller) ThingTagRepository {
+				return mocks.NewThingTagRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - tag repository error (begin tx)",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			tagRepoMock: func(mc *minimock.Controller) interfaces.TagRepository {
-				mock := repoMocks.NewTagRepositoryMock(mc)
+			tagRepoMock: func(mc *minimock.Controller) TagRepository {
+				mock := mocks.NewTagRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, tagID, id)
@@ -111,16 +111,16 @@ func Test_DeleteTagHandler(t *testing.T) {
 
 				return mock
 			},
-			thingTagRepoMock: func(mc *minimock.Controller) interfaces.ThingTagRepository {
-				return repoMocks.NewThingTagRepositoryMock(mc)
+			thingTagRepoMock: func(mc *minimock.Controller) ThingTagRepository {
+				return mocks.NewThingTagRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - thing tag repository error (delete)",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			tagRepoMock: func(mc *minimock.Controller) interfaces.TagRepository {
-				mock := repoMocks.NewTagRepositoryMock(mc)
+			tagRepoMock: func(mc *minimock.Controller) TagRepository {
+				mock := mocks.NewTagRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, tagID, id)
@@ -130,8 +130,8 @@ func Test_DeleteTagHandler(t *testing.T) {
 
 				return mock
 			},
-			thingTagRepoMock: func(mc *minimock.Controller) interfaces.ThingTagRepository {
-				mock := repoMocks.NewThingTagRepositoryMock(mc)
+			thingTagRepoMock: func(mc *minimock.Controller) ThingTagRepository {
+				mock := mocks.NewThingTagRepositoryMock(mc)
 
 				mock.DeleteByTagIDMock.Inspect(func(ctx context.Context, id int, tx *sql.Tx) {
 					assert.Equal(mc, tagID, id)
@@ -144,8 +144,8 @@ func Test_DeleteTagHandler(t *testing.T) {
 			name:    "negative case - tag repository error (delete)",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			tagRepoMock: func(mc *minimock.Controller) interfaces.TagRepository {
-				mock := repoMocks.NewTagRepositoryMock(mc)
+			tagRepoMock: func(mc *minimock.Controller) TagRepository {
+				mock := mocks.NewTagRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, tagID, id)
@@ -159,8 +159,8 @@ func Test_DeleteTagHandler(t *testing.T) {
 
 				return mock
 			},
-			thingTagRepoMock: func(mc *minimock.Controller) interfaces.ThingTagRepository {
-				mock := repoMocks.NewThingTagRepositoryMock(mc)
+			thingTagRepoMock: func(mc *minimock.Controller) ThingTagRepository {
+				mock := mocks.NewThingTagRepositoryMock(mc)
 
 				mock.DeleteByTagIDMock.Inspect(func(ctx context.Context, id int, tx *sql.Tx) {
 					assert.Equal(mc, tagID, id)
@@ -173,8 +173,8 @@ func Test_DeleteTagHandler(t *testing.T) {
 			name:    "negative case - tag repository error (commit tx)",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			tagRepoMock: func(mc *minimock.Controller) interfaces.TagRepository {
-				mock := repoMocks.NewTagRepositoryMock(mc)
+			tagRepoMock: func(mc *minimock.Controller) TagRepository {
+				mock := mocks.NewTagRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, tagID, id)
@@ -190,8 +190,8 @@ func Test_DeleteTagHandler(t *testing.T) {
 
 				return mock
 			},
-			thingTagRepoMock: func(mc *minimock.Controller) interfaces.ThingTagRepository {
-				mock := repoMocks.NewThingTagRepositoryMock(mc)
+			thingTagRepoMock: func(mc *minimock.Controller) ThingTagRepository {
+				mock := mocks.NewThingTagRepositoryMock(mc)
 
 				mock.DeleteByTagIDMock.Inspect(func(ctx context.Context, id int, tx *sql.Tx) {
 					assert.Equal(mc, tagID, id)
@@ -205,8 +205,8 @@ func Test_DeleteTagHandler(t *testing.T) {
 			req:     correctReq,
 			resCode: fiber.StatusOK,
 			resBody: dto.EmptyResponse{},
-			tagRepoMock: func(mc *minimock.Controller) interfaces.TagRepository {
-				mock := repoMocks.NewTagRepositoryMock(mc)
+			tagRepoMock: func(mc *minimock.Controller) TagRepository {
+				mock := mocks.NewTagRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, tagID, id)
@@ -222,8 +222,8 @@ func Test_DeleteTagHandler(t *testing.T) {
 
 				return mock
 			},
-			thingTagRepoMock: func(mc *minimock.Controller) interfaces.ThingTagRepository {
-				mock := repoMocks.NewThingTagRepositoryMock(mc)
+			thingTagRepoMock: func(mc *minimock.Controller) ThingTagRepository {
+				mock := mocks.NewThingTagRepositoryMock(mc)
 
 				mock.DeleteByTagIDMock.Inspect(func(ctx context.Context, id int, tx *sql.Tx) {
 					assert.Equal(mc, tagID, id)
@@ -236,10 +236,11 @@ func Test_DeleteTagHandler(t *testing.T) {
 
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			fiberApp := fiber.New()
-			serviceProvider := sp.InitMock(tt.tagRepoMock(mc), tt.thingTagRepoMock(mc))
+			t.Parallel()
 
-			fiberApp.Delete("/v1/tags/:tagId", DeleteTagHandler(serviceProvider))
+			mc := minimock.NewController(t)
+			fiberApp := fiber.New()
+			fiberApp.Delete("/v1/tags/:tagId", DeleteTagHandler(tt.tagRepoMock(mc), tt.thingTagRepoMock(mc)))
 
 			fiberReq := httptest.NewRequest(tt.req.method, tt.req.route, nil)
 			fiberReq.Header.Add(fiber.HeaderContentType, tt.req.contentType)

+ 13 - 8
internal/api/v1/tag/delete_thing_tag.go

@@ -2,11 +2,12 @@ package tag
 
 import (
 	"database/sql"
+	"errors"
+
+	"github.com/gofiber/fiber/v2"
 
 	"git.dmitriygnatenko.ru/dima/homethings/internal/factory"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/mappers"
-	"github.com/gofiber/fiber/v2"
 )
 
 // @Router 		/api/v1/tags/{tagId}/thing/{thingId} [delete]
@@ -20,7 +21,11 @@ import (
 // @security 	APIKey
 // @Accept      json
 // @Produce     json
-func DeleteThingTagHandler(sp interfaces.ServiceProvider) fiber.Handler {
+func DeleteThingTagHandler(
+	tagRepository TagRepository,
+	thingRepository ThingRepository,
+	thingTagRepository ThingTagRepository,
+) fiber.Handler {
 	return func(fctx *fiber.Ctx) error {
 		ctx := fctx.Context()
 		tagID, err := fctx.ParamsInt("tagId")
@@ -33,21 +38,21 @@ func DeleteThingTagHandler(sp interfaces.ServiceProvider) fiber.Handler {
 			return fiber.NewError(fiber.StatusBadRequest, err.Error())
 		}
 
-		if _, err = sp.GetTagRepository().Get(ctx, tagID); err != nil {
-			if err == sql.ErrNoRows {
+		if _, err = tagRepository.Get(ctx, tagID); err != nil {
+			if errors.Is(err, sql.ErrNoRows) {
 				return fiber.NewError(fiber.StatusBadRequest, "")
 			}
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
-		if _, err = sp.GetThingRepository().Get(ctx, thingID); err != nil {
-			if err == sql.ErrNoRows {
+		if _, err = thingRepository.Get(ctx, thingID); err != nil {
+			if errors.Is(err, sql.ErrNoRows) {
 				return fiber.NewError(fiber.StatusBadRequest, "")
 			}
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
-		if err = sp.GetThingTagRepository().Delete(ctx, mappers.ConvertToDeleteThingTagRequestModel(tagID, thingID), nil); err != nil {
+		if err = thingTagRepository.Delete(ctx, mappers.ToDeleteThingTagRequest(tagID, thingID), nil); err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 

+ 68 - 62
internal/api/v1/tag/delete_thing_tag_test.go

@@ -8,20 +8,21 @@ import (
 	"strconv"
 	"testing"
 
-	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
-	repoMocks "git.dmitriygnatenko.ru/dima/homethings/internal/repositories/mocks"
-	sp "git.dmitriygnatenko.ru/dima/homethings/internal/service_provider"
 	"github.com/brianvoe/gofakeit/v6"
 	"github.com/gofiber/fiber/v2"
 	"github.com/gojuno/minimock/v3"
 	"github.com/stretchr/testify/assert"
+
+	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/tag/mocks"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
 )
 
-func Test_DeleteThingTagHandler(t *testing.T) {
+func TestDeleteThingTagHandler(t *testing.T) {
+	t.Parallel()
+
 	type req struct {
 		method      string
 		route       string
@@ -29,7 +30,6 @@ func Test_DeleteThingTagHandler(t *testing.T) {
 	}
 
 	var (
-		mc        = minimock.NewController(t)
 		tagID     = gofakeit.Number(1, 1000)
 		thingID   = gofakeit.Number(1, 1000)
 		testError = errors.New(gofakeit.Phrase())
@@ -46,17 +46,17 @@ func Test_DeleteThingTagHandler(t *testing.T) {
 		req              req
 		resCode          int
 		resBody          interface{}
-		tagRepoMock      func(mc *minimock.Controller) interfaces.TagRepository
-		thingRepoMock    func(mc *minimock.Controller) interfaces.ThingRepository
-		thingTagRepoMock func(mc *minimock.Controller) interfaces.ThingTagRepository
+		tagRepoMock      func(mc *minimock.Controller) TagRepository
+		thingRepoMock    func(mc *minimock.Controller) ThingRepository
+		thingTagRepoMock func(mc *minimock.Controller) ThingTagRepository
 	}{
 		{
 			name:    "positive case",
 			req:     correctReq,
 			resCode: fiber.StatusOK,
 			resBody: dto.EmptyResponse{},
-			tagRepoMock: func(mc *minimock.Controller) interfaces.TagRepository {
-				mock := repoMocks.NewTagRepositoryMock(mc)
+			tagRepoMock: func(mc *minimock.Controller) TagRepository {
+				mock := mocks.NewTagRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, tagID, id)
@@ -64,8 +64,8 @@ func Test_DeleteThingTagHandler(t *testing.T) {
 
 				return mock
 			},
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				mock := repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				mock := mocks.NewThingRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -73,8 +73,8 @@ func Test_DeleteThingTagHandler(t *testing.T) {
 
 				return mock
 			},
-			thingTagRepoMock: func(mc *minimock.Controller) interfaces.ThingTagRepository {
-				mock := repoMocks.NewThingTagRepositoryMock(mc)
+			thingTagRepoMock: func(mc *minimock.Controller) ThingTagRepository {
+				mock := mocks.NewThingTagRepositoryMock(mc)
 
 				mock.DeleteMock.Inspect(func(ctx context.Context, req models.DeleteThingTagRequest, tx *sql.Tx) {
 					assert.Equal(mc, tagID, req.TagID)
@@ -92,14 +92,14 @@ func Test_DeleteThingTagHandler(t *testing.T) {
 				contentType: fiber.MIMEApplicationJSON,
 			},
 			resCode: fiber.StatusBadRequest,
-			tagRepoMock: func(mc *minimock.Controller) interfaces.TagRepository {
-				return repoMocks.NewTagRepositoryMock(mc)
+			tagRepoMock: func(mc *minimock.Controller) TagRepository {
+				return mocks.NewTagRepositoryMock(mc)
 			},
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				return repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				return mocks.NewThingRepositoryMock(mc)
 			},
-			thingTagRepoMock: func(mc *minimock.Controller) interfaces.ThingTagRepository {
-				return repoMocks.NewThingTagRepositoryMock(mc)
+			thingTagRepoMock: func(mc *minimock.Controller) ThingTagRepository {
+				return mocks.NewThingTagRepositoryMock(mc)
 			},
 		},
 		{
@@ -110,22 +110,22 @@ func Test_DeleteThingTagHandler(t *testing.T) {
 				contentType: fiber.MIMEApplicationJSON,
 			},
 			resCode: fiber.StatusBadRequest,
-			tagRepoMock: func(mc *minimock.Controller) interfaces.TagRepository {
-				return repoMocks.NewTagRepositoryMock(mc)
+			tagRepoMock: func(mc *minimock.Controller) TagRepository {
+				return mocks.NewTagRepositoryMock(mc)
 			},
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				return repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				return mocks.NewThingRepositoryMock(mc)
 			},
-			thingTagRepoMock: func(mc *minimock.Controller) interfaces.ThingTagRepository {
-				return repoMocks.NewThingTagRepositoryMock(mc)
+			thingTagRepoMock: func(mc *minimock.Controller) ThingTagRepository {
+				return mocks.NewThingTagRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - tag is not exist",
 			req:     correctReq,
 			resCode: fiber.StatusBadRequest,
-			tagRepoMock: func(mc *minimock.Controller) interfaces.TagRepository {
-				mock := repoMocks.NewTagRepositoryMock(mc)
+			tagRepoMock: func(mc *minimock.Controller) TagRepository {
+				mock := mocks.NewTagRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, tagID, id)
@@ -133,19 +133,19 @@ func Test_DeleteThingTagHandler(t *testing.T) {
 
 				return mock
 			},
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				return repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				return mocks.NewThingRepositoryMock(mc)
 			},
-			thingTagRepoMock: func(mc *minimock.Controller) interfaces.ThingTagRepository {
-				return repoMocks.NewThingTagRepositoryMock(mc)
+			thingTagRepoMock: func(mc *minimock.Controller) ThingTagRepository {
+				return mocks.NewThingTagRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - tag repository error",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			tagRepoMock: func(mc *minimock.Controller) interfaces.TagRepository {
-				mock := repoMocks.NewTagRepositoryMock(mc)
+			tagRepoMock: func(mc *minimock.Controller) TagRepository {
+				mock := mocks.NewTagRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, tagID, id)
@@ -153,19 +153,19 @@ func Test_DeleteThingTagHandler(t *testing.T) {
 
 				return mock
 			},
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				return repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				return mocks.NewThingRepositoryMock(mc)
 			},
-			thingTagRepoMock: func(mc *minimock.Controller) interfaces.ThingTagRepository {
-				return repoMocks.NewThingTagRepositoryMock(mc)
+			thingTagRepoMock: func(mc *minimock.Controller) ThingTagRepository {
+				return mocks.NewThingTagRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - thing is not exist",
 			req:     correctReq,
 			resCode: fiber.StatusBadRequest,
-			tagRepoMock: func(mc *minimock.Controller) interfaces.TagRepository {
-				mock := repoMocks.NewTagRepositoryMock(mc)
+			tagRepoMock: func(mc *minimock.Controller) TagRepository {
+				mock := mocks.NewTagRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, tagID, id)
@@ -173,8 +173,8 @@ func Test_DeleteThingTagHandler(t *testing.T) {
 
 				return mock
 			},
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				mock := repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				mock := mocks.NewThingRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -182,16 +182,16 @@ func Test_DeleteThingTagHandler(t *testing.T) {
 
 				return mock
 			},
-			thingTagRepoMock: func(mc *minimock.Controller) interfaces.ThingTagRepository {
-				return repoMocks.NewThingTagRepositoryMock(mc)
+			thingTagRepoMock: func(mc *minimock.Controller) ThingTagRepository {
+				return mocks.NewThingTagRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - thing repository error",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			tagRepoMock: func(mc *minimock.Controller) interfaces.TagRepository {
-				mock := repoMocks.NewTagRepositoryMock(mc)
+			tagRepoMock: func(mc *minimock.Controller) TagRepository {
+				mock := mocks.NewTagRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, tagID, id)
@@ -199,8 +199,8 @@ func Test_DeleteThingTagHandler(t *testing.T) {
 
 				return mock
 			},
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				mock := repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				mock := mocks.NewThingRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -208,16 +208,16 @@ func Test_DeleteThingTagHandler(t *testing.T) {
 
 				return mock
 			},
-			thingTagRepoMock: func(mc *minimock.Controller) interfaces.ThingTagRepository {
-				return repoMocks.NewThingTagRepositoryMock(mc)
+			thingTagRepoMock: func(mc *minimock.Controller) ThingTagRepository {
+				return mocks.NewThingTagRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - thing tag repository error",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			tagRepoMock: func(mc *minimock.Controller) interfaces.TagRepository {
-				mock := repoMocks.NewTagRepositoryMock(mc)
+			tagRepoMock: func(mc *minimock.Controller) TagRepository {
+				mock := mocks.NewTagRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, tagID, id)
@@ -225,8 +225,8 @@ func Test_DeleteThingTagHandler(t *testing.T) {
 
 				return mock
 			},
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				mock := repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				mock := mocks.NewThingRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -234,8 +234,8 @@ func Test_DeleteThingTagHandler(t *testing.T) {
 
 				return mock
 			},
-			thingTagRepoMock: func(mc *minimock.Controller) interfaces.ThingTagRepository {
-				mock := repoMocks.NewThingTagRepositoryMock(mc)
+			thingTagRepoMock: func(mc *minimock.Controller) ThingTagRepository {
+				mock := mocks.NewThingTagRepositoryMock(mc)
 
 				mock.DeleteMock.Inspect(func(ctx context.Context, req models.DeleteThingTagRequest, tx *sql.Tx) {
 					assert.Equal(mc, tagID, req.TagID)
@@ -249,10 +249,16 @@ func Test_DeleteThingTagHandler(t *testing.T) {
 
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
+			t.Parallel()
+
+			mc := minimock.NewController(t)
 			fiberApp := fiber.New()
-			serviceProvider := sp.InitMock(tt.tagRepoMock(mc), tt.thingRepoMock(mc), tt.thingTagRepoMock(mc))
 
-			fiberApp.Delete("/v1/tags/:tagId/thing/:thingId", DeleteThingTagHandler(serviceProvider))
+			fiberApp.Delete("/v1/tags/:tagId/thing/:thingId", DeleteThingTagHandler(
+				tt.tagRepoMock(mc),
+				tt.thingRepoMock(mc),
+				tt.thingTagRepoMock(mc),
+			))
 
 			fiberReq := httptest.NewRequest(tt.req.method, tt.req.route, nil)
 			fiberReq.Header.Add(fiber.HeaderContentType, tt.req.contentType)

+ 7 - 6
internal/api/v1/tag/get_tag.go

@@ -2,11 +2,12 @@ package tag
 
 import (
 	"database/sql"
+	"errors"
+
+	"github.com/gofiber/fiber/v2"
 
 	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/mappers"
-	"github.com/gofiber/fiber/v2"
 )
 
 // @Router 		/api/v1/tags/{tagId} [get]
@@ -20,7 +21,7 @@ import (
 // @security 	APIKey
 // @Accept      json
 // @Produce     json
-func GetTagHandler(sp interfaces.ServiceProvider) fiber.Handler {
+func GetTagHandler(tagRepository TagRepository) fiber.Handler {
 	return func(fctx *fiber.Ctx) error {
 		ctx := fctx.Context()
 		id, err := fctx.ParamsInt("tagId")
@@ -28,9 +29,9 @@ func GetTagHandler(sp interfaces.ServiceProvider) fiber.Handler {
 			return fiber.NewError(fiber.StatusBadRequest, err.Error())
 		}
 
-		res, err := sp.GetTagRepository().Get(ctx, id)
+		res, err := tagRepository.Get(ctx, id)
 		if err != nil {
-			if err == sql.ErrNoRows {
+			if errors.Is(err, sql.ErrNoRows) {
 				return fiber.NewError(fiber.StatusNotFound, "")
 			}
 
@@ -39,6 +40,6 @@ func GetTagHandler(sp interfaces.ServiceProvider) fiber.Handler {
 
 		res = helpers.ApplyLocation(fctx, res)
 
-		return fctx.JSON(mappers.ConvertToTagResponseDTO(*res))
+		return fctx.JSON(mappers.ToTagResponse(*res))
 	}
 }

+ 22 - 21
internal/api/v1/tag/get_tag_test.go

@@ -8,27 +8,27 @@ import (
 	"strconv"
 	"testing"
 
-	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
-	repoMocks "git.dmitriygnatenko.ru/dima/homethings/internal/repositories/mocks"
-	sp "git.dmitriygnatenko.ru/dima/homethings/internal/service_provider"
 	"github.com/brianvoe/gofakeit/v6"
 	"github.com/gofiber/fiber/v2"
 	"github.com/gojuno/minimock/v3"
 	"github.com/stretchr/testify/assert"
+
+	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/tag/mocks"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
 )
 
-func Test_GetTagHandler(t *testing.T) {
+func TestGetTagHandler(t *testing.T) {
+	t.Parallel()
+
 	type req struct {
 		method string
 		route  string
 	}
 
 	var (
-		mc        = minimock.NewController(t)
 		tagID     = gofakeit.Number(1, 1000)
 		testError = errors.New(gofakeit.Phrase())
 		layout    = "2006-01-02 15:04:05"
@@ -60,15 +60,15 @@ func Test_GetTagHandler(t *testing.T) {
 		req         req
 		resCode     int
 		resBody     interface{}
-		tagRepoMock func(mc *minimock.Controller) interfaces.TagRepository
+		tagRepoMock func(mc *minimock.Controller) TagRepository
 	}{
 		{
 			name:    "positive case",
 			req:     correctReq,
 			resCode: fiber.StatusOK,
 			resBody: expectedRes,
-			tagRepoMock: func(mc *minimock.Controller) interfaces.TagRepository {
-				mock := repoMocks.NewTagRepositoryMock(mc)
+			tagRepoMock: func(mc *minimock.Controller) TagRepository {
+				mock := mocks.NewTagRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, tagID, id)
@@ -81,8 +81,8 @@ func Test_GetTagHandler(t *testing.T) {
 			name:    "negative case - not found",
 			req:     correctReq,
 			resCode: fiber.StatusNotFound,
-			tagRepoMock: func(mc *minimock.Controller) interfaces.TagRepository {
-				mock := repoMocks.NewTagRepositoryMock(mc)
+			tagRepoMock: func(mc *minimock.Controller) TagRepository {
+				mock := mocks.NewTagRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, tagID, id)
@@ -95,8 +95,8 @@ func Test_GetTagHandler(t *testing.T) {
 			name:    "negative case - repository error",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			tagRepoMock: func(mc *minimock.Controller) interfaces.TagRepository {
-				mock := repoMocks.NewTagRepositoryMock(mc)
+			tagRepoMock: func(mc *minimock.Controller) TagRepository {
+				mock := mocks.NewTagRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, tagID, id)
@@ -113,18 +113,19 @@ func Test_GetTagHandler(t *testing.T) {
 			},
 			resCode: fiber.StatusBadRequest,
 			resBody: nil,
-			tagRepoMock: func(mc *minimock.Controller) interfaces.TagRepository {
-				return repoMocks.NewTagRepositoryMock(mc)
+			tagRepoMock: func(mc *minimock.Controller) TagRepository {
+				return mocks.NewTagRepositoryMock(mc)
 			},
 		},
 	}
 
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			fiberApp := fiber.New()
-			serviceProvider := sp.InitMock(tt.tagRepoMock(mc))
+			t.Parallel()
 
-			fiberApp.Get("/v1/tags/:tagId", GetTagHandler(serviceProvider))
+			mc := minimock.NewController(t)
+			fiberApp := fiber.New()
+			fiberApp.Get("/v1/tags/:tagId", GetTagHandler(tt.tagRepoMock(mc)))
 
 			fiberRes, _ := fiberApp.Test(httptest.NewRequest(tt.req.method, tt.req.route, nil), API.DefaultTestTimeOut)
 			assert.Equal(t, tt.resCode, fiberRes.StatusCode)

+ 5 - 5
internal/api/v1/tag/get_tags.go

@@ -1,10 +1,10 @@
 package tag
 
 import (
+	"github.com/gofiber/fiber/v2"
+
 	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/mappers"
-	"github.com/gofiber/fiber/v2"
 )
 
 // @Router 		/api/v1/tags [get]
@@ -16,15 +16,15 @@ import (
 // @security 	APIKey
 // @Accept      json
 // @Produce     json
-func GetTagsHandler(sp interfaces.ServiceProvider) fiber.Handler {
+func GetTagsHandler(tagRepository TagRepository) fiber.Handler {
 	return func(fctx *fiber.Ctx) error {
-		res, err := sp.GetTagRepository().GetAll(fctx.Context())
+		res, err := tagRepository.GetAll(fctx.Context())
 		if err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
 		res = helpers.ApplyLocation(fctx, res)
 
-		return fctx.JSON(mappers.ConvertToTagsResponseDTO(res))
+		return fctx.JSON(mappers.ToTagsResponse(res))
 	}
 }

+ 18 - 17
internal/api/v1/tag/get_tags_test.go

@@ -5,27 +5,27 @@ import (
 	"net/http/httptest"
 	"testing"
 
-	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
-	repoMocks "git.dmitriygnatenko.ru/dima/homethings/internal/repositories/mocks"
-	sp "git.dmitriygnatenko.ru/dima/homethings/internal/service_provider"
 	"github.com/brianvoe/gofakeit/v6"
 	"github.com/gofiber/fiber/v2"
 	"github.com/gojuno/minimock/v3"
 	"github.com/stretchr/testify/assert"
+
+	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/tag/mocks"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
 )
 
-func Test_GetTagsHandler(t *testing.T) {
+func TestGetTagsHandler(t *testing.T) {
+	t.Parallel()
+
 	type req struct {
 		method string
 		route  string
 	}
 
 	var (
-		mc        = minimock.NewController(t)
 		testError = errors.New(gofakeit.Phrase())
 		layout    = "2006-01-02 15:04:05"
 
@@ -76,15 +76,15 @@ func Test_GetTagsHandler(t *testing.T) {
 		req         req
 		resCode     int
 		resBody     interface{}
-		tagRepoMock func(mc *minimock.Controller) interfaces.TagRepository
+		tagRepoMock func(mc *minimock.Controller) TagRepository
 	}{
 		{
 			name:    "positive case",
 			req:     correctReq,
 			resCode: fiber.StatusOK,
 			resBody: expectedRes,
-			tagRepoMock: func(mc *minimock.Controller) interfaces.TagRepository {
-				mock := repoMocks.NewTagRepositoryMock(mc)
+			tagRepoMock: func(mc *minimock.Controller) TagRepository {
+				mock := mocks.NewTagRepositoryMock(mc)
 				mock.GetAllMock.Return(tagRepoRes, nil)
 				return mock
 			},
@@ -93,8 +93,8 @@ func Test_GetTagsHandler(t *testing.T) {
 			name:    "negative case - repository error",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			tagRepoMock: func(mc *minimock.Controller) interfaces.TagRepository {
-				mock := repoMocks.NewTagRepositoryMock(mc)
+			tagRepoMock: func(mc *minimock.Controller) TagRepository {
+				mock := mocks.NewTagRepositoryMock(mc)
 				mock.GetAllMock.Return(nil, testError)
 				return mock
 			},
@@ -103,10 +103,11 @@ func Test_GetTagsHandler(t *testing.T) {
 
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			fiberApp := fiber.New()
-			serviceProvider := sp.InitMock(tt.tagRepoMock(mc))
+			t.Parallel()
 
-			fiberApp.Get("/v1/tags", GetTagsHandler(serviceProvider))
+			mc := minimock.NewController(t)
+			fiberApp := fiber.New()
+			fiberApp.Get("/v1/tags", GetTagsHandler(tt.tagRepoMock(mc)))
 
 			fiberRes, _ := fiberApp.Test(httptest.NewRequest(tt.req.method, tt.req.route, nil), API.DefaultTestTimeOut)
 			assert.Equal(t, tt.resCode, fiberRes.StatusCode)

+ 5 - 5
internal/api/v1/tag/get_thing_tags.go

@@ -1,10 +1,10 @@
 package tag
 
 import (
+	"github.com/gofiber/fiber/v2"
+
 	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/mappers"
-	"github.com/gofiber/fiber/v2"
 )
 
 // @Router 		/api/v1/tags/thing/{thingId} [get]
@@ -17,7 +17,7 @@ import (
 // @security 	APIKey
 // @Accept      json
 // @Produce     json
-func GetThingTagsHandler(sp interfaces.ServiceProvider) fiber.Handler {
+func GetThingTagsHandler(tagRepository TagRepository) fiber.Handler {
 	return func(fctx *fiber.Ctx) error {
 		ctx := fctx.Context()
 		id, err := fctx.ParamsInt("thingId")
@@ -25,13 +25,13 @@ func GetThingTagsHandler(sp interfaces.ServiceProvider) fiber.Handler {
 			return fiber.NewError(fiber.StatusBadRequest, err.Error())
 		}
 
-		res, err := sp.GetTagRepository().GetByThingID(ctx, id)
+		res, err := tagRepository.GetByThingID(ctx, id)
 		if err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
 		res = helpers.ApplyLocation(fctx, res)
 
-		return fctx.JSON(mappers.ConvertToTagsResponseDTO(res))
+		return fctx.JSON(mappers.ToTagsResponse(res))
 	}
 }

+ 20 - 19
internal/api/v1/tag/get_thing_tags_test.go

@@ -7,27 +7,27 @@ import (
 	"strconv"
 	"testing"
 
-	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
-	repoMocks "git.dmitriygnatenko.ru/dima/homethings/internal/repositories/mocks"
-	sp "git.dmitriygnatenko.ru/dima/homethings/internal/service_provider"
 	"github.com/brianvoe/gofakeit/v6"
 	"github.com/gofiber/fiber/v2"
 	"github.com/gojuno/minimock/v3"
 	"github.com/stretchr/testify/assert"
+
+	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/tag/mocks"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
 )
 
-func Test_GetThingTagsHandler(t *testing.T) {
+func TestGetThingTagsHandler(t *testing.T) {
+	t.Parallel()
+
 	type req struct {
 		method string
 		route  string
 	}
 
 	var (
-		mc        = minimock.NewController(t)
 		thingID   = gofakeit.Number(1, 1000)
 		testError = errors.New(gofakeit.Phrase())
 		layout    = "2006-01-02 15:04:05"
@@ -79,15 +79,15 @@ func Test_GetThingTagsHandler(t *testing.T) {
 		req         req
 		resCode     int
 		resBody     interface{}
-		tagRepoMock func(mc *minimock.Controller) interfaces.TagRepository
+		tagRepoMock func(mc *minimock.Controller) TagRepository
 	}{
 		{
 			name:    "positive case",
 			req:     correctReq,
 			resCode: fiber.StatusOK,
 			resBody: expectedRes,
-			tagRepoMock: func(mc *minimock.Controller) interfaces.TagRepository {
-				mock := repoMocks.NewTagRepositoryMock(mc)
+			tagRepoMock: func(mc *minimock.Controller) TagRepository {
+				mock := mocks.NewTagRepositoryMock(mc)
 
 				mock.GetByThingIDMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -100,8 +100,8 @@ func Test_GetThingTagsHandler(t *testing.T) {
 			name:    "negative case - repository error",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			tagRepoMock: func(mc *minimock.Controller) interfaces.TagRepository {
-				mock := repoMocks.NewTagRepositoryMock(mc)
+			tagRepoMock: func(mc *minimock.Controller) TagRepository {
+				mock := mocks.NewTagRepositoryMock(mc)
 
 				mock.GetByThingIDMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -118,18 +118,19 @@ func Test_GetThingTagsHandler(t *testing.T) {
 			},
 			resCode: fiber.StatusBadRequest,
 			resBody: nil,
-			tagRepoMock: func(mc *minimock.Controller) interfaces.TagRepository {
-				return repoMocks.NewTagRepositoryMock(mc)
+			tagRepoMock: func(mc *minimock.Controller) TagRepository {
+				return mocks.NewTagRepositoryMock(mc)
 			},
 		},
 	}
 
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			fiberApp := fiber.New()
-			serviceProvider := sp.InitMock(tt.tagRepoMock(mc))
+			t.Parallel()
 
-			fiberApp.Get("/v1/tags/thing/:thingId", GetThingTagsHandler(serviceProvider))
+			mc := minimock.NewController(t)
+			fiberApp := fiber.New()
+			fiberApp.Get("/v1/tags/thing/:thingId", GetThingTagsHandler(tt.tagRepoMock(mc)))
 
 			fiberRes, _ := fiberApp.Test(httptest.NewRequest(tt.req.method, tt.req.route, nil), API.DefaultTestTimeOut)
 			assert.Equal(t, tt.resCode, fiberRes.StatusCode)

File diff ditekan karena terlalu besar
+ 525 - 84
internal/api/v1/tag/mocks/tag_repository_minimock.go


+ 395 - 0
internal/api/v1/tag/mocks/thing_repository_minimock.go

@@ -0,0 +1,395 @@
+// Code generated by http://github.com/gojuno/minimock (v3.3.13). DO NOT EDIT.
+
+package mocks
+
+//go:generate minimock -i git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/tag.ThingRepository -o thing_repository_minimock.go -n ThingRepositoryMock -p mocks
+
+import (
+	"context"
+	"sync"
+	mm_atomic "sync/atomic"
+	mm_time "time"
+
+	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
+	"github.com/gojuno/minimock/v3"
+)
+
+// ThingRepositoryMock implements tag.ThingRepository
+type ThingRepositoryMock struct {
+	t          minimock.Tester
+	finishOnce sync.Once
+
+	funcGet          func(ctx context.Context, thingID int) (tp1 *models.Thing, err error)
+	inspectFuncGet   func(ctx context.Context, thingID int)
+	afterGetCounter  uint64
+	beforeGetCounter uint64
+	GetMock          mThingRepositoryMockGet
+}
+
+// NewThingRepositoryMock returns a mock for tag.ThingRepository
+func NewThingRepositoryMock(t minimock.Tester) *ThingRepositoryMock {
+	m := &ThingRepositoryMock{t: t}
+
+	if controller, ok := t.(minimock.MockController); ok {
+		controller.RegisterMocker(m)
+	}
+
+	m.GetMock = mThingRepositoryMockGet{mock: m}
+	m.GetMock.callArgs = []*ThingRepositoryMockGetParams{}
+
+	t.Cleanup(m.MinimockFinish)
+
+	return m
+}
+
+type mThingRepositoryMockGet struct {
+	optional           bool
+	mock               *ThingRepositoryMock
+	defaultExpectation *ThingRepositoryMockGetExpectation
+	expectations       []*ThingRepositoryMockGetExpectation
+
+	callArgs []*ThingRepositoryMockGetParams
+	mutex    sync.RWMutex
+
+	expectedInvocations uint64
+}
+
+// ThingRepositoryMockGetExpectation specifies expectation struct of the ThingRepository.Get
+type ThingRepositoryMockGetExpectation struct {
+	mock      *ThingRepositoryMock
+	params    *ThingRepositoryMockGetParams
+	paramPtrs *ThingRepositoryMockGetParamPtrs
+	results   *ThingRepositoryMockGetResults
+	Counter   uint64
+}
+
+// ThingRepositoryMockGetParams contains parameters of the ThingRepository.Get
+type ThingRepositoryMockGetParams struct {
+	ctx     context.Context
+	thingID int
+}
+
+// ThingRepositoryMockGetParamPtrs contains pointers to parameters of the ThingRepository.Get
+type ThingRepositoryMockGetParamPtrs struct {
+	ctx     *context.Context
+	thingID *int
+}
+
+// ThingRepositoryMockGetResults contains results of the ThingRepository.Get
+type ThingRepositoryMockGetResults struct {
+	tp1 *models.Thing
+	err error
+}
+
+// Marks this method to be optional. The default behavior of any method with Return() is '1 or more', meaning
+// the test will fail minimock's automatic final call check if the mocked method was not called at least once.
+// Optional() makes method check to work in '0 or more' mode.
+// It is NOT RECOMMENDED to use this option unless you really need it, as default behaviour helps to
+// catch the problems when the expected method call is totally skipped during test run.
+func (mmGet *mThingRepositoryMockGet) Optional() *mThingRepositoryMockGet {
+	mmGet.optional = true
+	return mmGet
+}
+
+// Expect sets up expected params for ThingRepository.Get
+func (mmGet *mThingRepositoryMockGet) Expect(ctx context.Context, thingID int) *mThingRepositoryMockGet {
+	if mmGet.mock.funcGet != nil {
+		mmGet.mock.t.Fatalf("ThingRepositoryMock.Get mock is already set by Set")
+	}
+
+	if mmGet.defaultExpectation == nil {
+		mmGet.defaultExpectation = &ThingRepositoryMockGetExpectation{}
+	}
+
+	if mmGet.defaultExpectation.paramPtrs != nil {
+		mmGet.mock.t.Fatalf("ThingRepositoryMock.Get mock is already set by ExpectParams functions")
+	}
+
+	mmGet.defaultExpectation.params = &ThingRepositoryMockGetParams{ctx, thingID}
+	for _, e := range mmGet.expectations {
+		if minimock.Equal(e.params, mmGet.defaultExpectation.params) {
+			mmGet.mock.t.Fatalf("Expectation set by When has same params: %#v", *mmGet.defaultExpectation.params)
+		}
+	}
+
+	return mmGet
+}
+
+// ExpectCtxParam1 sets up expected param ctx for ThingRepository.Get
+func (mmGet *mThingRepositoryMockGet) ExpectCtxParam1(ctx context.Context) *mThingRepositoryMockGet {
+	if mmGet.mock.funcGet != nil {
+		mmGet.mock.t.Fatalf("ThingRepositoryMock.Get mock is already set by Set")
+	}
+
+	if mmGet.defaultExpectation == nil {
+		mmGet.defaultExpectation = &ThingRepositoryMockGetExpectation{}
+	}
+
+	if mmGet.defaultExpectation.params != nil {
+		mmGet.mock.t.Fatalf("ThingRepositoryMock.Get mock is already set by Expect")
+	}
+
+	if mmGet.defaultExpectation.paramPtrs == nil {
+		mmGet.defaultExpectation.paramPtrs = &ThingRepositoryMockGetParamPtrs{}
+	}
+	mmGet.defaultExpectation.paramPtrs.ctx = &ctx
+
+	return mmGet
+}
+
+// ExpectThingIDParam2 sets up expected param thingID for ThingRepository.Get
+func (mmGet *mThingRepositoryMockGet) ExpectThingIDParam2(thingID int) *mThingRepositoryMockGet {
+	if mmGet.mock.funcGet != nil {
+		mmGet.mock.t.Fatalf("ThingRepositoryMock.Get mock is already set by Set")
+	}
+
+	if mmGet.defaultExpectation == nil {
+		mmGet.defaultExpectation = &ThingRepositoryMockGetExpectation{}
+	}
+
+	if mmGet.defaultExpectation.params != nil {
+		mmGet.mock.t.Fatalf("ThingRepositoryMock.Get mock is already set by Expect")
+	}
+
+	if mmGet.defaultExpectation.paramPtrs == nil {
+		mmGet.defaultExpectation.paramPtrs = &ThingRepositoryMockGetParamPtrs{}
+	}
+	mmGet.defaultExpectation.paramPtrs.thingID = &thingID
+
+	return mmGet
+}
+
+// Inspect accepts an inspector function that has same arguments as the ThingRepository.Get
+func (mmGet *mThingRepositoryMockGet) Inspect(f func(ctx context.Context, thingID int)) *mThingRepositoryMockGet {
+	if mmGet.mock.inspectFuncGet != nil {
+		mmGet.mock.t.Fatalf("Inspect function is already set for ThingRepositoryMock.Get")
+	}
+
+	mmGet.mock.inspectFuncGet = f
+
+	return mmGet
+}
+
+// Return sets up results that will be returned by ThingRepository.Get
+func (mmGet *mThingRepositoryMockGet) Return(tp1 *models.Thing, err error) *ThingRepositoryMock {
+	if mmGet.mock.funcGet != nil {
+		mmGet.mock.t.Fatalf("ThingRepositoryMock.Get mock is already set by Set")
+	}
+
+	if mmGet.defaultExpectation == nil {
+		mmGet.defaultExpectation = &ThingRepositoryMockGetExpectation{mock: mmGet.mock}
+	}
+	mmGet.defaultExpectation.results = &ThingRepositoryMockGetResults{tp1, err}
+	return mmGet.mock
+}
+
+// Set uses given function f to mock the ThingRepository.Get method
+func (mmGet *mThingRepositoryMockGet) Set(f func(ctx context.Context, thingID int) (tp1 *models.Thing, err error)) *ThingRepositoryMock {
+	if mmGet.defaultExpectation != nil {
+		mmGet.mock.t.Fatalf("Default expectation is already set for the ThingRepository.Get method")
+	}
+
+	if len(mmGet.expectations) > 0 {
+		mmGet.mock.t.Fatalf("Some expectations are already set for the ThingRepository.Get method")
+	}
+
+	mmGet.mock.funcGet = f
+	return mmGet.mock
+}
+
+// When sets expectation for the ThingRepository.Get which will trigger the result defined by the following
+// Then helper
+func (mmGet *mThingRepositoryMockGet) When(ctx context.Context, thingID int) *ThingRepositoryMockGetExpectation {
+	if mmGet.mock.funcGet != nil {
+		mmGet.mock.t.Fatalf("ThingRepositoryMock.Get mock is already set by Set")
+	}
+
+	expectation := &ThingRepositoryMockGetExpectation{
+		mock:   mmGet.mock,
+		params: &ThingRepositoryMockGetParams{ctx, thingID},
+	}
+	mmGet.expectations = append(mmGet.expectations, expectation)
+	return expectation
+}
+
+// Then sets up ThingRepository.Get return parameters for the expectation previously defined by the When method
+func (e *ThingRepositoryMockGetExpectation) Then(tp1 *models.Thing, err error) *ThingRepositoryMock {
+	e.results = &ThingRepositoryMockGetResults{tp1, err}
+	return e.mock
+}
+
+// Times sets number of times ThingRepository.Get should be invoked
+func (mmGet *mThingRepositoryMockGet) Times(n uint64) *mThingRepositoryMockGet {
+	if n == 0 {
+		mmGet.mock.t.Fatalf("Times of ThingRepositoryMock.Get mock can not be zero")
+	}
+	mm_atomic.StoreUint64(&mmGet.expectedInvocations, n)
+	return mmGet
+}
+
+func (mmGet *mThingRepositoryMockGet) invocationsDone() bool {
+	if len(mmGet.expectations) == 0 && mmGet.defaultExpectation == nil && mmGet.mock.funcGet == nil {
+		return true
+	}
+
+	totalInvocations := mm_atomic.LoadUint64(&mmGet.mock.afterGetCounter)
+	expectedInvocations := mm_atomic.LoadUint64(&mmGet.expectedInvocations)
+
+	return totalInvocations > 0 && (expectedInvocations == 0 || expectedInvocations == totalInvocations)
+}
+
+// Get implements tag.ThingRepository
+func (mmGet *ThingRepositoryMock) Get(ctx context.Context, thingID int) (tp1 *models.Thing, err error) {
+	mm_atomic.AddUint64(&mmGet.beforeGetCounter, 1)
+	defer mm_atomic.AddUint64(&mmGet.afterGetCounter, 1)
+
+	if mmGet.inspectFuncGet != nil {
+		mmGet.inspectFuncGet(ctx, thingID)
+	}
+
+	mm_params := ThingRepositoryMockGetParams{ctx, thingID}
+
+	// Record call args
+	mmGet.GetMock.mutex.Lock()
+	mmGet.GetMock.callArgs = append(mmGet.GetMock.callArgs, &mm_params)
+	mmGet.GetMock.mutex.Unlock()
+
+	for _, e := range mmGet.GetMock.expectations {
+		if minimock.Equal(*e.params, mm_params) {
+			mm_atomic.AddUint64(&e.Counter, 1)
+			return e.results.tp1, e.results.err
+		}
+	}
+
+	if mmGet.GetMock.defaultExpectation != nil {
+		mm_atomic.AddUint64(&mmGet.GetMock.defaultExpectation.Counter, 1)
+		mm_want := mmGet.GetMock.defaultExpectation.params
+		mm_want_ptrs := mmGet.GetMock.defaultExpectation.paramPtrs
+
+		mm_got := ThingRepositoryMockGetParams{ctx, thingID}
+
+		if mm_want_ptrs != nil {
+
+			if mm_want_ptrs.ctx != nil && !minimock.Equal(*mm_want_ptrs.ctx, mm_got.ctx) {
+				mmGet.t.Errorf("ThingRepositoryMock.Get got unexpected parameter ctx, want: %#v, got: %#v%s\n", *mm_want_ptrs.ctx, mm_got.ctx, minimock.Diff(*mm_want_ptrs.ctx, mm_got.ctx))
+			}
+
+			if mm_want_ptrs.thingID != nil && !minimock.Equal(*mm_want_ptrs.thingID, mm_got.thingID) {
+				mmGet.t.Errorf("ThingRepositoryMock.Get got unexpected parameter thingID, want: %#v, got: %#v%s\n", *mm_want_ptrs.thingID, mm_got.thingID, minimock.Diff(*mm_want_ptrs.thingID, mm_got.thingID))
+			}
+
+		} else if mm_want != nil && !minimock.Equal(*mm_want, mm_got) {
+			mmGet.t.Errorf("ThingRepositoryMock.Get got unexpected parameters, want: %#v, got: %#v%s\n", *mm_want, mm_got, minimock.Diff(*mm_want, mm_got))
+		}
+
+		mm_results := mmGet.GetMock.defaultExpectation.results
+		if mm_results == nil {
+			mmGet.t.Fatal("No results are set for the ThingRepositoryMock.Get")
+		}
+		return (*mm_results).tp1, (*mm_results).err
+	}
+	if mmGet.funcGet != nil {
+		return mmGet.funcGet(ctx, thingID)
+	}
+	mmGet.t.Fatalf("Unexpected call to ThingRepositoryMock.Get. %v %v", ctx, thingID)
+	return
+}
+
+// GetAfterCounter returns a count of finished ThingRepositoryMock.Get invocations
+func (mmGet *ThingRepositoryMock) GetAfterCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmGet.afterGetCounter)
+}
+
+// GetBeforeCounter returns a count of ThingRepositoryMock.Get invocations
+func (mmGet *ThingRepositoryMock) GetBeforeCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmGet.beforeGetCounter)
+}
+
+// Calls returns a list of arguments used in each call to ThingRepositoryMock.Get.
+// The list is in the same order as the calls were made (i.e. recent calls have a higher index)
+func (mmGet *mThingRepositoryMockGet) Calls() []*ThingRepositoryMockGetParams {
+	mmGet.mutex.RLock()
+
+	argCopy := make([]*ThingRepositoryMockGetParams, len(mmGet.callArgs))
+	copy(argCopy, mmGet.callArgs)
+
+	mmGet.mutex.RUnlock()
+
+	return argCopy
+}
+
+// MinimockGetDone returns true if the count of the Get invocations corresponds
+// the number of defined expectations
+func (m *ThingRepositoryMock) MinimockGetDone() bool {
+	if m.GetMock.optional {
+		// Optional methods provide '0 or more' call count restriction.
+		return true
+	}
+
+	for _, e := range m.GetMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			return false
+		}
+	}
+
+	return m.GetMock.invocationsDone()
+}
+
+// MinimockGetInspect logs each unmet expectation
+func (m *ThingRepositoryMock) MinimockGetInspect() {
+	for _, e := range m.GetMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			m.t.Errorf("Expected call to ThingRepositoryMock.Get with params: %#v", *e.params)
+		}
+	}
+
+	afterGetCounter := mm_atomic.LoadUint64(&m.afterGetCounter)
+	// if default expectation was set then invocations count should be greater than zero
+	if m.GetMock.defaultExpectation != nil && afterGetCounter < 1 {
+		if m.GetMock.defaultExpectation.params == nil {
+			m.t.Error("Expected call to ThingRepositoryMock.Get")
+		} else {
+			m.t.Errorf("Expected call to ThingRepositoryMock.Get with params: %#v", *m.GetMock.defaultExpectation.params)
+		}
+	}
+	// if func was set then invocations count should be greater than zero
+	if m.funcGet != nil && afterGetCounter < 1 {
+		m.t.Error("Expected call to ThingRepositoryMock.Get")
+	}
+
+	if !m.GetMock.invocationsDone() && afterGetCounter > 0 {
+		m.t.Errorf("Expected %d calls to ThingRepositoryMock.Get but found %d calls",
+			mm_atomic.LoadUint64(&m.GetMock.expectedInvocations), afterGetCounter)
+	}
+}
+
+// MinimockFinish checks that all mocked methods have been called the expected number of times
+func (m *ThingRepositoryMock) MinimockFinish() {
+	m.finishOnce.Do(func() {
+		if !m.minimockDone() {
+			m.MinimockGetInspect()
+		}
+	})
+}
+
+// MinimockWait waits for all mocked methods to be called the expected number of times
+func (m *ThingRepositoryMock) MinimockWait(timeout mm_time.Duration) {
+	timeoutCh := mm_time.After(timeout)
+	for {
+		if m.minimockDone() {
+			return
+		}
+		select {
+		case <-timeoutCh:
+			m.MinimockFinish()
+			return
+		case <-mm_time.After(10 * mm_time.Millisecond):
+		}
+	}
+}
+
+func (m *ThingRepositoryMock) minimockDone() bool {
+	done := true
+	return done &&
+		m.MinimockGetDone()
+}

+ 1143 - 0
internal/api/v1/tag/mocks/thing_tag_repository_minimock.go

@@ -0,0 +1,1143 @@
+// Code generated by http://github.com/gojuno/minimock (v3.3.13). DO NOT EDIT.
+
+package mocks
+
+//go:generate minimock -i git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/tag.ThingTagRepository -o thing_tag_repository_minimock.go -n ThingTagRepositoryMock -p mocks
+
+import (
+	"context"
+	"database/sql"
+	"sync"
+	mm_atomic "sync/atomic"
+	mm_time "time"
+
+	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
+	"github.com/gojuno/minimock/v3"
+)
+
+// ThingTagRepositoryMock implements tag.ThingTagRepository
+type ThingTagRepositoryMock struct {
+	t          minimock.Tester
+	finishOnce sync.Once
+
+	funcAdd          func(ctx context.Context, req models.AddThingTagRequest, tx *sql.Tx) (err error)
+	inspectFuncAdd   func(ctx context.Context, req models.AddThingTagRequest, tx *sql.Tx)
+	afterAddCounter  uint64
+	beforeAddCounter uint64
+	AddMock          mThingTagRepositoryMockAdd
+
+	funcDelete          func(ctx context.Context, req models.DeleteThingTagRequest, tx *sql.Tx) (err error)
+	inspectFuncDelete   func(ctx context.Context, req models.DeleteThingTagRequest, tx *sql.Tx)
+	afterDeleteCounter  uint64
+	beforeDeleteCounter uint64
+	DeleteMock          mThingTagRepositoryMockDelete
+
+	funcDeleteByTagID          func(ctx context.Context, tagID int, tx *sql.Tx) (err error)
+	inspectFuncDeleteByTagID   func(ctx context.Context, tagID int, tx *sql.Tx)
+	afterDeleteByTagIDCounter  uint64
+	beforeDeleteByTagIDCounter uint64
+	DeleteByTagIDMock          mThingTagRepositoryMockDeleteByTagID
+}
+
+// NewThingTagRepositoryMock returns a mock for tag.ThingTagRepository
+func NewThingTagRepositoryMock(t minimock.Tester) *ThingTagRepositoryMock {
+	m := &ThingTagRepositoryMock{t: t}
+
+	if controller, ok := t.(minimock.MockController); ok {
+		controller.RegisterMocker(m)
+	}
+
+	m.AddMock = mThingTagRepositoryMockAdd{mock: m}
+	m.AddMock.callArgs = []*ThingTagRepositoryMockAddParams{}
+
+	m.DeleteMock = mThingTagRepositoryMockDelete{mock: m}
+	m.DeleteMock.callArgs = []*ThingTagRepositoryMockDeleteParams{}
+
+	m.DeleteByTagIDMock = mThingTagRepositoryMockDeleteByTagID{mock: m}
+	m.DeleteByTagIDMock.callArgs = []*ThingTagRepositoryMockDeleteByTagIDParams{}
+
+	t.Cleanup(m.MinimockFinish)
+
+	return m
+}
+
+type mThingTagRepositoryMockAdd struct {
+	optional           bool
+	mock               *ThingTagRepositoryMock
+	defaultExpectation *ThingTagRepositoryMockAddExpectation
+	expectations       []*ThingTagRepositoryMockAddExpectation
+
+	callArgs []*ThingTagRepositoryMockAddParams
+	mutex    sync.RWMutex
+
+	expectedInvocations uint64
+}
+
+// ThingTagRepositoryMockAddExpectation specifies expectation struct of the ThingTagRepository.Add
+type ThingTagRepositoryMockAddExpectation struct {
+	mock      *ThingTagRepositoryMock
+	params    *ThingTagRepositoryMockAddParams
+	paramPtrs *ThingTagRepositoryMockAddParamPtrs
+	results   *ThingTagRepositoryMockAddResults
+	Counter   uint64
+}
+
+// ThingTagRepositoryMockAddParams contains parameters of the ThingTagRepository.Add
+type ThingTagRepositoryMockAddParams struct {
+	ctx context.Context
+	req models.AddThingTagRequest
+	tx  *sql.Tx
+}
+
+// ThingTagRepositoryMockAddParamPtrs contains pointers to parameters of the ThingTagRepository.Add
+type ThingTagRepositoryMockAddParamPtrs struct {
+	ctx *context.Context
+	req *models.AddThingTagRequest
+	tx  **sql.Tx
+}
+
+// ThingTagRepositoryMockAddResults contains results of the ThingTagRepository.Add
+type ThingTagRepositoryMockAddResults struct {
+	err error
+}
+
+// Marks this method to be optional. The default behavior of any method with Return() is '1 or more', meaning
+// the test will fail minimock's automatic final call check if the mocked method was not called at least once.
+// Optional() makes method check to work in '0 or more' mode.
+// It is NOT RECOMMENDED to use this option unless you really need it, as default behaviour helps to
+// catch the problems when the expected method call is totally skipped during test run.
+func (mmAdd *mThingTagRepositoryMockAdd) Optional() *mThingTagRepositoryMockAdd {
+	mmAdd.optional = true
+	return mmAdd
+}
+
+// Expect sets up expected params for ThingTagRepository.Add
+func (mmAdd *mThingTagRepositoryMockAdd) Expect(ctx context.Context, req models.AddThingTagRequest, tx *sql.Tx) *mThingTagRepositoryMockAdd {
+	if mmAdd.mock.funcAdd != nil {
+		mmAdd.mock.t.Fatalf("ThingTagRepositoryMock.Add mock is already set by Set")
+	}
+
+	if mmAdd.defaultExpectation == nil {
+		mmAdd.defaultExpectation = &ThingTagRepositoryMockAddExpectation{}
+	}
+
+	if mmAdd.defaultExpectation.paramPtrs != nil {
+		mmAdd.mock.t.Fatalf("ThingTagRepositoryMock.Add mock is already set by ExpectParams functions")
+	}
+
+	mmAdd.defaultExpectation.params = &ThingTagRepositoryMockAddParams{ctx, req, tx}
+	for _, e := range mmAdd.expectations {
+		if minimock.Equal(e.params, mmAdd.defaultExpectation.params) {
+			mmAdd.mock.t.Fatalf("Expectation set by When has same params: %#v", *mmAdd.defaultExpectation.params)
+		}
+	}
+
+	return mmAdd
+}
+
+// ExpectCtxParam1 sets up expected param ctx for ThingTagRepository.Add
+func (mmAdd *mThingTagRepositoryMockAdd) ExpectCtxParam1(ctx context.Context) *mThingTagRepositoryMockAdd {
+	if mmAdd.mock.funcAdd != nil {
+		mmAdd.mock.t.Fatalf("ThingTagRepositoryMock.Add mock is already set by Set")
+	}
+
+	if mmAdd.defaultExpectation == nil {
+		mmAdd.defaultExpectation = &ThingTagRepositoryMockAddExpectation{}
+	}
+
+	if mmAdd.defaultExpectation.params != nil {
+		mmAdd.mock.t.Fatalf("ThingTagRepositoryMock.Add mock is already set by Expect")
+	}
+
+	if mmAdd.defaultExpectation.paramPtrs == nil {
+		mmAdd.defaultExpectation.paramPtrs = &ThingTagRepositoryMockAddParamPtrs{}
+	}
+	mmAdd.defaultExpectation.paramPtrs.ctx = &ctx
+
+	return mmAdd
+}
+
+// ExpectReqParam2 sets up expected param req for ThingTagRepository.Add
+func (mmAdd *mThingTagRepositoryMockAdd) ExpectReqParam2(req models.AddThingTagRequest) *mThingTagRepositoryMockAdd {
+	if mmAdd.mock.funcAdd != nil {
+		mmAdd.mock.t.Fatalf("ThingTagRepositoryMock.Add mock is already set by Set")
+	}
+
+	if mmAdd.defaultExpectation == nil {
+		mmAdd.defaultExpectation = &ThingTagRepositoryMockAddExpectation{}
+	}
+
+	if mmAdd.defaultExpectation.params != nil {
+		mmAdd.mock.t.Fatalf("ThingTagRepositoryMock.Add mock is already set by Expect")
+	}
+
+	if mmAdd.defaultExpectation.paramPtrs == nil {
+		mmAdd.defaultExpectation.paramPtrs = &ThingTagRepositoryMockAddParamPtrs{}
+	}
+	mmAdd.defaultExpectation.paramPtrs.req = &req
+
+	return mmAdd
+}
+
+// ExpectTxParam3 sets up expected param tx for ThingTagRepository.Add
+func (mmAdd *mThingTagRepositoryMockAdd) ExpectTxParam3(tx *sql.Tx) *mThingTagRepositoryMockAdd {
+	if mmAdd.mock.funcAdd != nil {
+		mmAdd.mock.t.Fatalf("ThingTagRepositoryMock.Add mock is already set by Set")
+	}
+
+	if mmAdd.defaultExpectation == nil {
+		mmAdd.defaultExpectation = &ThingTagRepositoryMockAddExpectation{}
+	}
+
+	if mmAdd.defaultExpectation.params != nil {
+		mmAdd.mock.t.Fatalf("ThingTagRepositoryMock.Add mock is already set by Expect")
+	}
+
+	if mmAdd.defaultExpectation.paramPtrs == nil {
+		mmAdd.defaultExpectation.paramPtrs = &ThingTagRepositoryMockAddParamPtrs{}
+	}
+	mmAdd.defaultExpectation.paramPtrs.tx = &tx
+
+	return mmAdd
+}
+
+// Inspect accepts an inspector function that has same arguments as the ThingTagRepository.Add
+func (mmAdd *mThingTagRepositoryMockAdd) Inspect(f func(ctx context.Context, req models.AddThingTagRequest, tx *sql.Tx)) *mThingTagRepositoryMockAdd {
+	if mmAdd.mock.inspectFuncAdd != nil {
+		mmAdd.mock.t.Fatalf("Inspect function is already set for ThingTagRepositoryMock.Add")
+	}
+
+	mmAdd.mock.inspectFuncAdd = f
+
+	return mmAdd
+}
+
+// Return sets up results that will be returned by ThingTagRepository.Add
+func (mmAdd *mThingTagRepositoryMockAdd) Return(err error) *ThingTagRepositoryMock {
+	if mmAdd.mock.funcAdd != nil {
+		mmAdd.mock.t.Fatalf("ThingTagRepositoryMock.Add mock is already set by Set")
+	}
+
+	if mmAdd.defaultExpectation == nil {
+		mmAdd.defaultExpectation = &ThingTagRepositoryMockAddExpectation{mock: mmAdd.mock}
+	}
+	mmAdd.defaultExpectation.results = &ThingTagRepositoryMockAddResults{err}
+	return mmAdd.mock
+}
+
+// Set uses given function f to mock the ThingTagRepository.Add method
+func (mmAdd *mThingTagRepositoryMockAdd) Set(f func(ctx context.Context, req models.AddThingTagRequest, tx *sql.Tx) (err error)) *ThingTagRepositoryMock {
+	if mmAdd.defaultExpectation != nil {
+		mmAdd.mock.t.Fatalf("Default expectation is already set for the ThingTagRepository.Add method")
+	}
+
+	if len(mmAdd.expectations) > 0 {
+		mmAdd.mock.t.Fatalf("Some expectations are already set for the ThingTagRepository.Add method")
+	}
+
+	mmAdd.mock.funcAdd = f
+	return mmAdd.mock
+}
+
+// When sets expectation for the ThingTagRepository.Add which will trigger the result defined by the following
+// Then helper
+func (mmAdd *mThingTagRepositoryMockAdd) When(ctx context.Context, req models.AddThingTagRequest, tx *sql.Tx) *ThingTagRepositoryMockAddExpectation {
+	if mmAdd.mock.funcAdd != nil {
+		mmAdd.mock.t.Fatalf("ThingTagRepositoryMock.Add mock is already set by Set")
+	}
+
+	expectation := &ThingTagRepositoryMockAddExpectation{
+		mock:   mmAdd.mock,
+		params: &ThingTagRepositoryMockAddParams{ctx, req, tx},
+	}
+	mmAdd.expectations = append(mmAdd.expectations, expectation)
+	return expectation
+}
+
+// Then sets up ThingTagRepository.Add return parameters for the expectation previously defined by the When method
+func (e *ThingTagRepositoryMockAddExpectation) Then(err error) *ThingTagRepositoryMock {
+	e.results = &ThingTagRepositoryMockAddResults{err}
+	return e.mock
+}
+
+// Times sets number of times ThingTagRepository.Add should be invoked
+func (mmAdd *mThingTagRepositoryMockAdd) Times(n uint64) *mThingTagRepositoryMockAdd {
+	if n == 0 {
+		mmAdd.mock.t.Fatalf("Times of ThingTagRepositoryMock.Add mock can not be zero")
+	}
+	mm_atomic.StoreUint64(&mmAdd.expectedInvocations, n)
+	return mmAdd
+}
+
+func (mmAdd *mThingTagRepositoryMockAdd) invocationsDone() bool {
+	if len(mmAdd.expectations) == 0 && mmAdd.defaultExpectation == nil && mmAdd.mock.funcAdd == nil {
+		return true
+	}
+
+	totalInvocations := mm_atomic.LoadUint64(&mmAdd.mock.afterAddCounter)
+	expectedInvocations := mm_atomic.LoadUint64(&mmAdd.expectedInvocations)
+
+	return totalInvocations > 0 && (expectedInvocations == 0 || expectedInvocations == totalInvocations)
+}
+
+// Add implements tag.ThingTagRepository
+func (mmAdd *ThingTagRepositoryMock) Add(ctx context.Context, req models.AddThingTagRequest, tx *sql.Tx) (err error) {
+	mm_atomic.AddUint64(&mmAdd.beforeAddCounter, 1)
+	defer mm_atomic.AddUint64(&mmAdd.afterAddCounter, 1)
+
+	if mmAdd.inspectFuncAdd != nil {
+		mmAdd.inspectFuncAdd(ctx, req, tx)
+	}
+
+	mm_params := ThingTagRepositoryMockAddParams{ctx, req, tx}
+
+	// Record call args
+	mmAdd.AddMock.mutex.Lock()
+	mmAdd.AddMock.callArgs = append(mmAdd.AddMock.callArgs, &mm_params)
+	mmAdd.AddMock.mutex.Unlock()
+
+	for _, e := range mmAdd.AddMock.expectations {
+		if minimock.Equal(*e.params, mm_params) {
+			mm_atomic.AddUint64(&e.Counter, 1)
+			return e.results.err
+		}
+	}
+
+	if mmAdd.AddMock.defaultExpectation != nil {
+		mm_atomic.AddUint64(&mmAdd.AddMock.defaultExpectation.Counter, 1)
+		mm_want := mmAdd.AddMock.defaultExpectation.params
+		mm_want_ptrs := mmAdd.AddMock.defaultExpectation.paramPtrs
+
+		mm_got := ThingTagRepositoryMockAddParams{ctx, req, tx}
+
+		if mm_want_ptrs != nil {
+
+			if mm_want_ptrs.ctx != nil && !minimock.Equal(*mm_want_ptrs.ctx, mm_got.ctx) {
+				mmAdd.t.Errorf("ThingTagRepositoryMock.Add got unexpected parameter ctx, want: %#v, got: %#v%s\n", *mm_want_ptrs.ctx, mm_got.ctx, minimock.Diff(*mm_want_ptrs.ctx, mm_got.ctx))
+			}
+
+			if mm_want_ptrs.req != nil && !minimock.Equal(*mm_want_ptrs.req, mm_got.req) {
+				mmAdd.t.Errorf("ThingTagRepositoryMock.Add got unexpected parameter req, want: %#v, got: %#v%s\n", *mm_want_ptrs.req, mm_got.req, minimock.Diff(*mm_want_ptrs.req, mm_got.req))
+			}
+
+			if mm_want_ptrs.tx != nil && !minimock.Equal(*mm_want_ptrs.tx, mm_got.tx) {
+				mmAdd.t.Errorf("ThingTagRepositoryMock.Add got unexpected parameter tx, want: %#v, got: %#v%s\n", *mm_want_ptrs.tx, mm_got.tx, minimock.Diff(*mm_want_ptrs.tx, mm_got.tx))
+			}
+
+		} else if mm_want != nil && !minimock.Equal(*mm_want, mm_got) {
+			mmAdd.t.Errorf("ThingTagRepositoryMock.Add got unexpected parameters, want: %#v, got: %#v%s\n", *mm_want, mm_got, minimock.Diff(*mm_want, mm_got))
+		}
+
+		mm_results := mmAdd.AddMock.defaultExpectation.results
+		if mm_results == nil {
+			mmAdd.t.Fatal("No results are set for the ThingTagRepositoryMock.Add")
+		}
+		return (*mm_results).err
+	}
+	if mmAdd.funcAdd != nil {
+		return mmAdd.funcAdd(ctx, req, tx)
+	}
+	mmAdd.t.Fatalf("Unexpected call to ThingTagRepositoryMock.Add. %v %v %v", ctx, req, tx)
+	return
+}
+
+// AddAfterCounter returns a count of finished ThingTagRepositoryMock.Add invocations
+func (mmAdd *ThingTagRepositoryMock) AddAfterCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmAdd.afterAddCounter)
+}
+
+// AddBeforeCounter returns a count of ThingTagRepositoryMock.Add invocations
+func (mmAdd *ThingTagRepositoryMock) AddBeforeCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmAdd.beforeAddCounter)
+}
+
+// Calls returns a list of arguments used in each call to ThingTagRepositoryMock.Add.
+// The list is in the same order as the calls were made (i.e. recent calls have a higher index)
+func (mmAdd *mThingTagRepositoryMockAdd) Calls() []*ThingTagRepositoryMockAddParams {
+	mmAdd.mutex.RLock()
+
+	argCopy := make([]*ThingTagRepositoryMockAddParams, len(mmAdd.callArgs))
+	copy(argCopy, mmAdd.callArgs)
+
+	mmAdd.mutex.RUnlock()
+
+	return argCopy
+}
+
+// MinimockAddDone returns true if the count of the Add invocations corresponds
+// the number of defined expectations
+func (m *ThingTagRepositoryMock) MinimockAddDone() bool {
+	if m.AddMock.optional {
+		// Optional methods provide '0 or more' call count restriction.
+		return true
+	}
+
+	for _, e := range m.AddMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			return false
+		}
+	}
+
+	return m.AddMock.invocationsDone()
+}
+
+// MinimockAddInspect logs each unmet expectation
+func (m *ThingTagRepositoryMock) MinimockAddInspect() {
+	for _, e := range m.AddMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			m.t.Errorf("Expected call to ThingTagRepositoryMock.Add with params: %#v", *e.params)
+		}
+	}
+
+	afterAddCounter := mm_atomic.LoadUint64(&m.afterAddCounter)
+	// if default expectation was set then invocations count should be greater than zero
+	if m.AddMock.defaultExpectation != nil && afterAddCounter < 1 {
+		if m.AddMock.defaultExpectation.params == nil {
+			m.t.Error("Expected call to ThingTagRepositoryMock.Add")
+		} else {
+			m.t.Errorf("Expected call to ThingTagRepositoryMock.Add with params: %#v", *m.AddMock.defaultExpectation.params)
+		}
+	}
+	// if func was set then invocations count should be greater than zero
+	if m.funcAdd != nil && afterAddCounter < 1 {
+		m.t.Error("Expected call to ThingTagRepositoryMock.Add")
+	}
+
+	if !m.AddMock.invocationsDone() && afterAddCounter > 0 {
+		m.t.Errorf("Expected %d calls to ThingTagRepositoryMock.Add but found %d calls",
+			mm_atomic.LoadUint64(&m.AddMock.expectedInvocations), afterAddCounter)
+	}
+}
+
+type mThingTagRepositoryMockDelete struct {
+	optional           bool
+	mock               *ThingTagRepositoryMock
+	defaultExpectation *ThingTagRepositoryMockDeleteExpectation
+	expectations       []*ThingTagRepositoryMockDeleteExpectation
+
+	callArgs []*ThingTagRepositoryMockDeleteParams
+	mutex    sync.RWMutex
+
+	expectedInvocations uint64
+}
+
+// ThingTagRepositoryMockDeleteExpectation specifies expectation struct of the ThingTagRepository.Delete
+type ThingTagRepositoryMockDeleteExpectation struct {
+	mock      *ThingTagRepositoryMock
+	params    *ThingTagRepositoryMockDeleteParams
+	paramPtrs *ThingTagRepositoryMockDeleteParamPtrs
+	results   *ThingTagRepositoryMockDeleteResults
+	Counter   uint64
+}
+
+// ThingTagRepositoryMockDeleteParams contains parameters of the ThingTagRepository.Delete
+type ThingTagRepositoryMockDeleteParams struct {
+	ctx context.Context
+	req models.DeleteThingTagRequest
+	tx  *sql.Tx
+}
+
+// ThingTagRepositoryMockDeleteParamPtrs contains pointers to parameters of the ThingTagRepository.Delete
+type ThingTagRepositoryMockDeleteParamPtrs struct {
+	ctx *context.Context
+	req *models.DeleteThingTagRequest
+	tx  **sql.Tx
+}
+
+// ThingTagRepositoryMockDeleteResults contains results of the ThingTagRepository.Delete
+type ThingTagRepositoryMockDeleteResults struct {
+	err error
+}
+
+// Marks this method to be optional. The default behavior of any method with Return() is '1 or more', meaning
+// the test will fail minimock's automatic final call check if the mocked method was not called at least once.
+// Optional() makes method check to work in '0 or more' mode.
+// It is NOT RECOMMENDED to use this option unless you really need it, as default behaviour helps to
+// catch the problems when the expected method call is totally skipped during test run.
+func (mmDelete *mThingTagRepositoryMockDelete) Optional() *mThingTagRepositoryMockDelete {
+	mmDelete.optional = true
+	return mmDelete
+}
+
+// Expect sets up expected params for ThingTagRepository.Delete
+func (mmDelete *mThingTagRepositoryMockDelete) Expect(ctx context.Context, req models.DeleteThingTagRequest, tx *sql.Tx) *mThingTagRepositoryMockDelete {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("ThingTagRepositoryMock.Delete mock is already set by Set")
+	}
+
+	if mmDelete.defaultExpectation == nil {
+		mmDelete.defaultExpectation = &ThingTagRepositoryMockDeleteExpectation{}
+	}
+
+	if mmDelete.defaultExpectation.paramPtrs != nil {
+		mmDelete.mock.t.Fatalf("ThingTagRepositoryMock.Delete mock is already set by ExpectParams functions")
+	}
+
+	mmDelete.defaultExpectation.params = &ThingTagRepositoryMockDeleteParams{ctx, req, tx}
+	for _, e := range mmDelete.expectations {
+		if minimock.Equal(e.params, mmDelete.defaultExpectation.params) {
+			mmDelete.mock.t.Fatalf("Expectation set by When has same params: %#v", *mmDelete.defaultExpectation.params)
+		}
+	}
+
+	return mmDelete
+}
+
+// ExpectCtxParam1 sets up expected param ctx for ThingTagRepository.Delete
+func (mmDelete *mThingTagRepositoryMockDelete) ExpectCtxParam1(ctx context.Context) *mThingTagRepositoryMockDelete {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("ThingTagRepositoryMock.Delete mock is already set by Set")
+	}
+
+	if mmDelete.defaultExpectation == nil {
+		mmDelete.defaultExpectation = &ThingTagRepositoryMockDeleteExpectation{}
+	}
+
+	if mmDelete.defaultExpectation.params != nil {
+		mmDelete.mock.t.Fatalf("ThingTagRepositoryMock.Delete mock is already set by Expect")
+	}
+
+	if mmDelete.defaultExpectation.paramPtrs == nil {
+		mmDelete.defaultExpectation.paramPtrs = &ThingTagRepositoryMockDeleteParamPtrs{}
+	}
+	mmDelete.defaultExpectation.paramPtrs.ctx = &ctx
+
+	return mmDelete
+}
+
+// ExpectReqParam2 sets up expected param req for ThingTagRepository.Delete
+func (mmDelete *mThingTagRepositoryMockDelete) ExpectReqParam2(req models.DeleteThingTagRequest) *mThingTagRepositoryMockDelete {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("ThingTagRepositoryMock.Delete mock is already set by Set")
+	}
+
+	if mmDelete.defaultExpectation == nil {
+		mmDelete.defaultExpectation = &ThingTagRepositoryMockDeleteExpectation{}
+	}
+
+	if mmDelete.defaultExpectation.params != nil {
+		mmDelete.mock.t.Fatalf("ThingTagRepositoryMock.Delete mock is already set by Expect")
+	}
+
+	if mmDelete.defaultExpectation.paramPtrs == nil {
+		mmDelete.defaultExpectation.paramPtrs = &ThingTagRepositoryMockDeleteParamPtrs{}
+	}
+	mmDelete.defaultExpectation.paramPtrs.req = &req
+
+	return mmDelete
+}
+
+// ExpectTxParam3 sets up expected param tx for ThingTagRepository.Delete
+func (mmDelete *mThingTagRepositoryMockDelete) ExpectTxParam3(tx *sql.Tx) *mThingTagRepositoryMockDelete {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("ThingTagRepositoryMock.Delete mock is already set by Set")
+	}
+
+	if mmDelete.defaultExpectation == nil {
+		mmDelete.defaultExpectation = &ThingTagRepositoryMockDeleteExpectation{}
+	}
+
+	if mmDelete.defaultExpectation.params != nil {
+		mmDelete.mock.t.Fatalf("ThingTagRepositoryMock.Delete mock is already set by Expect")
+	}
+
+	if mmDelete.defaultExpectation.paramPtrs == nil {
+		mmDelete.defaultExpectation.paramPtrs = &ThingTagRepositoryMockDeleteParamPtrs{}
+	}
+	mmDelete.defaultExpectation.paramPtrs.tx = &tx
+
+	return mmDelete
+}
+
+// Inspect accepts an inspector function that has same arguments as the ThingTagRepository.Delete
+func (mmDelete *mThingTagRepositoryMockDelete) Inspect(f func(ctx context.Context, req models.DeleteThingTagRequest, tx *sql.Tx)) *mThingTagRepositoryMockDelete {
+	if mmDelete.mock.inspectFuncDelete != nil {
+		mmDelete.mock.t.Fatalf("Inspect function is already set for ThingTagRepositoryMock.Delete")
+	}
+
+	mmDelete.mock.inspectFuncDelete = f
+
+	return mmDelete
+}
+
+// Return sets up results that will be returned by ThingTagRepository.Delete
+func (mmDelete *mThingTagRepositoryMockDelete) Return(err error) *ThingTagRepositoryMock {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("ThingTagRepositoryMock.Delete mock is already set by Set")
+	}
+
+	if mmDelete.defaultExpectation == nil {
+		mmDelete.defaultExpectation = &ThingTagRepositoryMockDeleteExpectation{mock: mmDelete.mock}
+	}
+	mmDelete.defaultExpectation.results = &ThingTagRepositoryMockDeleteResults{err}
+	return mmDelete.mock
+}
+
+// Set uses given function f to mock the ThingTagRepository.Delete method
+func (mmDelete *mThingTagRepositoryMockDelete) Set(f func(ctx context.Context, req models.DeleteThingTagRequest, tx *sql.Tx) (err error)) *ThingTagRepositoryMock {
+	if mmDelete.defaultExpectation != nil {
+		mmDelete.mock.t.Fatalf("Default expectation is already set for the ThingTagRepository.Delete method")
+	}
+
+	if len(mmDelete.expectations) > 0 {
+		mmDelete.mock.t.Fatalf("Some expectations are already set for the ThingTagRepository.Delete method")
+	}
+
+	mmDelete.mock.funcDelete = f
+	return mmDelete.mock
+}
+
+// When sets expectation for the ThingTagRepository.Delete which will trigger the result defined by the following
+// Then helper
+func (mmDelete *mThingTagRepositoryMockDelete) When(ctx context.Context, req models.DeleteThingTagRequest, tx *sql.Tx) *ThingTagRepositoryMockDeleteExpectation {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("ThingTagRepositoryMock.Delete mock is already set by Set")
+	}
+
+	expectation := &ThingTagRepositoryMockDeleteExpectation{
+		mock:   mmDelete.mock,
+		params: &ThingTagRepositoryMockDeleteParams{ctx, req, tx},
+	}
+	mmDelete.expectations = append(mmDelete.expectations, expectation)
+	return expectation
+}
+
+// Then sets up ThingTagRepository.Delete return parameters for the expectation previously defined by the When method
+func (e *ThingTagRepositoryMockDeleteExpectation) Then(err error) *ThingTagRepositoryMock {
+	e.results = &ThingTagRepositoryMockDeleteResults{err}
+	return e.mock
+}
+
+// Times sets number of times ThingTagRepository.Delete should be invoked
+func (mmDelete *mThingTagRepositoryMockDelete) Times(n uint64) *mThingTagRepositoryMockDelete {
+	if n == 0 {
+		mmDelete.mock.t.Fatalf("Times of ThingTagRepositoryMock.Delete mock can not be zero")
+	}
+	mm_atomic.StoreUint64(&mmDelete.expectedInvocations, n)
+	return mmDelete
+}
+
+func (mmDelete *mThingTagRepositoryMockDelete) invocationsDone() bool {
+	if len(mmDelete.expectations) == 0 && mmDelete.defaultExpectation == nil && mmDelete.mock.funcDelete == nil {
+		return true
+	}
+
+	totalInvocations := mm_atomic.LoadUint64(&mmDelete.mock.afterDeleteCounter)
+	expectedInvocations := mm_atomic.LoadUint64(&mmDelete.expectedInvocations)
+
+	return totalInvocations > 0 && (expectedInvocations == 0 || expectedInvocations == totalInvocations)
+}
+
+// Delete implements tag.ThingTagRepository
+func (mmDelete *ThingTagRepositoryMock) Delete(ctx context.Context, req models.DeleteThingTagRequest, tx *sql.Tx) (err error) {
+	mm_atomic.AddUint64(&mmDelete.beforeDeleteCounter, 1)
+	defer mm_atomic.AddUint64(&mmDelete.afterDeleteCounter, 1)
+
+	if mmDelete.inspectFuncDelete != nil {
+		mmDelete.inspectFuncDelete(ctx, req, tx)
+	}
+
+	mm_params := ThingTagRepositoryMockDeleteParams{ctx, req, tx}
+
+	// Record call args
+	mmDelete.DeleteMock.mutex.Lock()
+	mmDelete.DeleteMock.callArgs = append(mmDelete.DeleteMock.callArgs, &mm_params)
+	mmDelete.DeleteMock.mutex.Unlock()
+
+	for _, e := range mmDelete.DeleteMock.expectations {
+		if minimock.Equal(*e.params, mm_params) {
+			mm_atomic.AddUint64(&e.Counter, 1)
+			return e.results.err
+		}
+	}
+
+	if mmDelete.DeleteMock.defaultExpectation != nil {
+		mm_atomic.AddUint64(&mmDelete.DeleteMock.defaultExpectation.Counter, 1)
+		mm_want := mmDelete.DeleteMock.defaultExpectation.params
+		mm_want_ptrs := mmDelete.DeleteMock.defaultExpectation.paramPtrs
+
+		mm_got := ThingTagRepositoryMockDeleteParams{ctx, req, tx}
+
+		if mm_want_ptrs != nil {
+
+			if mm_want_ptrs.ctx != nil && !minimock.Equal(*mm_want_ptrs.ctx, mm_got.ctx) {
+				mmDelete.t.Errorf("ThingTagRepositoryMock.Delete got unexpected parameter ctx, want: %#v, got: %#v%s\n", *mm_want_ptrs.ctx, mm_got.ctx, minimock.Diff(*mm_want_ptrs.ctx, mm_got.ctx))
+			}
+
+			if mm_want_ptrs.req != nil && !minimock.Equal(*mm_want_ptrs.req, mm_got.req) {
+				mmDelete.t.Errorf("ThingTagRepositoryMock.Delete got unexpected parameter req, want: %#v, got: %#v%s\n", *mm_want_ptrs.req, mm_got.req, minimock.Diff(*mm_want_ptrs.req, mm_got.req))
+			}
+
+			if mm_want_ptrs.tx != nil && !minimock.Equal(*mm_want_ptrs.tx, mm_got.tx) {
+				mmDelete.t.Errorf("ThingTagRepositoryMock.Delete got unexpected parameter tx, want: %#v, got: %#v%s\n", *mm_want_ptrs.tx, mm_got.tx, minimock.Diff(*mm_want_ptrs.tx, mm_got.tx))
+			}
+
+		} else if mm_want != nil && !minimock.Equal(*mm_want, mm_got) {
+			mmDelete.t.Errorf("ThingTagRepositoryMock.Delete got unexpected parameters, want: %#v, got: %#v%s\n", *mm_want, mm_got, minimock.Diff(*mm_want, mm_got))
+		}
+
+		mm_results := mmDelete.DeleteMock.defaultExpectation.results
+		if mm_results == nil {
+			mmDelete.t.Fatal("No results are set for the ThingTagRepositoryMock.Delete")
+		}
+		return (*mm_results).err
+	}
+	if mmDelete.funcDelete != nil {
+		return mmDelete.funcDelete(ctx, req, tx)
+	}
+	mmDelete.t.Fatalf("Unexpected call to ThingTagRepositoryMock.Delete. %v %v %v", ctx, req, tx)
+	return
+}
+
+// DeleteAfterCounter returns a count of finished ThingTagRepositoryMock.Delete invocations
+func (mmDelete *ThingTagRepositoryMock) DeleteAfterCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmDelete.afterDeleteCounter)
+}
+
+// DeleteBeforeCounter returns a count of ThingTagRepositoryMock.Delete invocations
+func (mmDelete *ThingTagRepositoryMock) DeleteBeforeCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmDelete.beforeDeleteCounter)
+}
+
+// Calls returns a list of arguments used in each call to ThingTagRepositoryMock.Delete.
+// The list is in the same order as the calls were made (i.e. recent calls have a higher index)
+func (mmDelete *mThingTagRepositoryMockDelete) Calls() []*ThingTagRepositoryMockDeleteParams {
+	mmDelete.mutex.RLock()
+
+	argCopy := make([]*ThingTagRepositoryMockDeleteParams, len(mmDelete.callArgs))
+	copy(argCopy, mmDelete.callArgs)
+
+	mmDelete.mutex.RUnlock()
+
+	return argCopy
+}
+
+// MinimockDeleteDone returns true if the count of the Delete invocations corresponds
+// the number of defined expectations
+func (m *ThingTagRepositoryMock) MinimockDeleteDone() bool {
+	if m.DeleteMock.optional {
+		// Optional methods provide '0 or more' call count restriction.
+		return true
+	}
+
+	for _, e := range m.DeleteMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			return false
+		}
+	}
+
+	return m.DeleteMock.invocationsDone()
+}
+
+// MinimockDeleteInspect logs each unmet expectation
+func (m *ThingTagRepositoryMock) MinimockDeleteInspect() {
+	for _, e := range m.DeleteMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			m.t.Errorf("Expected call to ThingTagRepositoryMock.Delete with params: %#v", *e.params)
+		}
+	}
+
+	afterDeleteCounter := mm_atomic.LoadUint64(&m.afterDeleteCounter)
+	// if default expectation was set then invocations count should be greater than zero
+	if m.DeleteMock.defaultExpectation != nil && afterDeleteCounter < 1 {
+		if m.DeleteMock.defaultExpectation.params == nil {
+			m.t.Error("Expected call to ThingTagRepositoryMock.Delete")
+		} else {
+			m.t.Errorf("Expected call to ThingTagRepositoryMock.Delete with params: %#v", *m.DeleteMock.defaultExpectation.params)
+		}
+	}
+	// if func was set then invocations count should be greater than zero
+	if m.funcDelete != nil && afterDeleteCounter < 1 {
+		m.t.Error("Expected call to ThingTagRepositoryMock.Delete")
+	}
+
+	if !m.DeleteMock.invocationsDone() && afterDeleteCounter > 0 {
+		m.t.Errorf("Expected %d calls to ThingTagRepositoryMock.Delete but found %d calls",
+			mm_atomic.LoadUint64(&m.DeleteMock.expectedInvocations), afterDeleteCounter)
+	}
+}
+
+type mThingTagRepositoryMockDeleteByTagID struct {
+	optional           bool
+	mock               *ThingTagRepositoryMock
+	defaultExpectation *ThingTagRepositoryMockDeleteByTagIDExpectation
+	expectations       []*ThingTagRepositoryMockDeleteByTagIDExpectation
+
+	callArgs []*ThingTagRepositoryMockDeleteByTagIDParams
+	mutex    sync.RWMutex
+
+	expectedInvocations uint64
+}
+
+// ThingTagRepositoryMockDeleteByTagIDExpectation specifies expectation struct of the ThingTagRepository.DeleteByTagID
+type ThingTagRepositoryMockDeleteByTagIDExpectation struct {
+	mock      *ThingTagRepositoryMock
+	params    *ThingTagRepositoryMockDeleteByTagIDParams
+	paramPtrs *ThingTagRepositoryMockDeleteByTagIDParamPtrs
+	results   *ThingTagRepositoryMockDeleteByTagIDResults
+	Counter   uint64
+}
+
+// ThingTagRepositoryMockDeleteByTagIDParams contains parameters of the ThingTagRepository.DeleteByTagID
+type ThingTagRepositoryMockDeleteByTagIDParams struct {
+	ctx   context.Context
+	tagID int
+	tx    *sql.Tx
+}
+
+// ThingTagRepositoryMockDeleteByTagIDParamPtrs contains pointers to parameters of the ThingTagRepository.DeleteByTagID
+type ThingTagRepositoryMockDeleteByTagIDParamPtrs struct {
+	ctx   *context.Context
+	tagID *int
+	tx    **sql.Tx
+}
+
+// ThingTagRepositoryMockDeleteByTagIDResults contains results of the ThingTagRepository.DeleteByTagID
+type ThingTagRepositoryMockDeleteByTagIDResults struct {
+	err error
+}
+
+// Marks this method to be optional. The default behavior of any method with Return() is '1 or more', meaning
+// the test will fail minimock's automatic final call check if the mocked method was not called at least once.
+// Optional() makes method check to work in '0 or more' mode.
+// It is NOT RECOMMENDED to use this option unless you really need it, as default behaviour helps to
+// catch the problems when the expected method call is totally skipped during test run.
+func (mmDeleteByTagID *mThingTagRepositoryMockDeleteByTagID) Optional() *mThingTagRepositoryMockDeleteByTagID {
+	mmDeleteByTagID.optional = true
+	return mmDeleteByTagID
+}
+
+// Expect sets up expected params for ThingTagRepository.DeleteByTagID
+func (mmDeleteByTagID *mThingTagRepositoryMockDeleteByTagID) Expect(ctx context.Context, tagID int, tx *sql.Tx) *mThingTagRepositoryMockDeleteByTagID {
+	if mmDeleteByTagID.mock.funcDeleteByTagID != nil {
+		mmDeleteByTagID.mock.t.Fatalf("ThingTagRepositoryMock.DeleteByTagID mock is already set by Set")
+	}
+
+	if mmDeleteByTagID.defaultExpectation == nil {
+		mmDeleteByTagID.defaultExpectation = &ThingTagRepositoryMockDeleteByTagIDExpectation{}
+	}
+
+	if mmDeleteByTagID.defaultExpectation.paramPtrs != nil {
+		mmDeleteByTagID.mock.t.Fatalf("ThingTagRepositoryMock.DeleteByTagID mock is already set by ExpectParams functions")
+	}
+
+	mmDeleteByTagID.defaultExpectation.params = &ThingTagRepositoryMockDeleteByTagIDParams{ctx, tagID, tx}
+	for _, e := range mmDeleteByTagID.expectations {
+		if minimock.Equal(e.params, mmDeleteByTagID.defaultExpectation.params) {
+			mmDeleteByTagID.mock.t.Fatalf("Expectation set by When has same params: %#v", *mmDeleteByTagID.defaultExpectation.params)
+		}
+	}
+
+	return mmDeleteByTagID
+}
+
+// ExpectCtxParam1 sets up expected param ctx for ThingTagRepository.DeleteByTagID
+func (mmDeleteByTagID *mThingTagRepositoryMockDeleteByTagID) ExpectCtxParam1(ctx context.Context) *mThingTagRepositoryMockDeleteByTagID {
+	if mmDeleteByTagID.mock.funcDeleteByTagID != nil {
+		mmDeleteByTagID.mock.t.Fatalf("ThingTagRepositoryMock.DeleteByTagID mock is already set by Set")
+	}
+
+	if mmDeleteByTagID.defaultExpectation == nil {
+		mmDeleteByTagID.defaultExpectation = &ThingTagRepositoryMockDeleteByTagIDExpectation{}
+	}
+
+	if mmDeleteByTagID.defaultExpectation.params != nil {
+		mmDeleteByTagID.mock.t.Fatalf("ThingTagRepositoryMock.DeleteByTagID mock is already set by Expect")
+	}
+
+	if mmDeleteByTagID.defaultExpectation.paramPtrs == nil {
+		mmDeleteByTagID.defaultExpectation.paramPtrs = &ThingTagRepositoryMockDeleteByTagIDParamPtrs{}
+	}
+	mmDeleteByTagID.defaultExpectation.paramPtrs.ctx = &ctx
+
+	return mmDeleteByTagID
+}
+
+// ExpectTagIDParam2 sets up expected param tagID for ThingTagRepository.DeleteByTagID
+func (mmDeleteByTagID *mThingTagRepositoryMockDeleteByTagID) ExpectTagIDParam2(tagID int) *mThingTagRepositoryMockDeleteByTagID {
+	if mmDeleteByTagID.mock.funcDeleteByTagID != nil {
+		mmDeleteByTagID.mock.t.Fatalf("ThingTagRepositoryMock.DeleteByTagID mock is already set by Set")
+	}
+
+	if mmDeleteByTagID.defaultExpectation == nil {
+		mmDeleteByTagID.defaultExpectation = &ThingTagRepositoryMockDeleteByTagIDExpectation{}
+	}
+
+	if mmDeleteByTagID.defaultExpectation.params != nil {
+		mmDeleteByTagID.mock.t.Fatalf("ThingTagRepositoryMock.DeleteByTagID mock is already set by Expect")
+	}
+
+	if mmDeleteByTagID.defaultExpectation.paramPtrs == nil {
+		mmDeleteByTagID.defaultExpectation.paramPtrs = &ThingTagRepositoryMockDeleteByTagIDParamPtrs{}
+	}
+	mmDeleteByTagID.defaultExpectation.paramPtrs.tagID = &tagID
+
+	return mmDeleteByTagID
+}
+
+// ExpectTxParam3 sets up expected param tx for ThingTagRepository.DeleteByTagID
+func (mmDeleteByTagID *mThingTagRepositoryMockDeleteByTagID) ExpectTxParam3(tx *sql.Tx) *mThingTagRepositoryMockDeleteByTagID {
+	if mmDeleteByTagID.mock.funcDeleteByTagID != nil {
+		mmDeleteByTagID.mock.t.Fatalf("ThingTagRepositoryMock.DeleteByTagID mock is already set by Set")
+	}
+
+	if mmDeleteByTagID.defaultExpectation == nil {
+		mmDeleteByTagID.defaultExpectation = &ThingTagRepositoryMockDeleteByTagIDExpectation{}
+	}
+
+	if mmDeleteByTagID.defaultExpectation.params != nil {
+		mmDeleteByTagID.mock.t.Fatalf("ThingTagRepositoryMock.DeleteByTagID mock is already set by Expect")
+	}
+
+	if mmDeleteByTagID.defaultExpectation.paramPtrs == nil {
+		mmDeleteByTagID.defaultExpectation.paramPtrs = &ThingTagRepositoryMockDeleteByTagIDParamPtrs{}
+	}
+	mmDeleteByTagID.defaultExpectation.paramPtrs.tx = &tx
+
+	return mmDeleteByTagID
+}
+
+// Inspect accepts an inspector function that has same arguments as the ThingTagRepository.DeleteByTagID
+func (mmDeleteByTagID *mThingTagRepositoryMockDeleteByTagID) Inspect(f func(ctx context.Context, tagID int, tx *sql.Tx)) *mThingTagRepositoryMockDeleteByTagID {
+	if mmDeleteByTagID.mock.inspectFuncDeleteByTagID != nil {
+		mmDeleteByTagID.mock.t.Fatalf("Inspect function is already set for ThingTagRepositoryMock.DeleteByTagID")
+	}
+
+	mmDeleteByTagID.mock.inspectFuncDeleteByTagID = f
+
+	return mmDeleteByTagID
+}
+
+// Return sets up results that will be returned by ThingTagRepository.DeleteByTagID
+func (mmDeleteByTagID *mThingTagRepositoryMockDeleteByTagID) Return(err error) *ThingTagRepositoryMock {
+	if mmDeleteByTagID.mock.funcDeleteByTagID != nil {
+		mmDeleteByTagID.mock.t.Fatalf("ThingTagRepositoryMock.DeleteByTagID mock is already set by Set")
+	}
+
+	if mmDeleteByTagID.defaultExpectation == nil {
+		mmDeleteByTagID.defaultExpectation = &ThingTagRepositoryMockDeleteByTagIDExpectation{mock: mmDeleteByTagID.mock}
+	}
+	mmDeleteByTagID.defaultExpectation.results = &ThingTagRepositoryMockDeleteByTagIDResults{err}
+	return mmDeleteByTagID.mock
+}
+
+// Set uses given function f to mock the ThingTagRepository.DeleteByTagID method
+func (mmDeleteByTagID *mThingTagRepositoryMockDeleteByTagID) Set(f func(ctx context.Context, tagID int, tx *sql.Tx) (err error)) *ThingTagRepositoryMock {
+	if mmDeleteByTagID.defaultExpectation != nil {
+		mmDeleteByTagID.mock.t.Fatalf("Default expectation is already set for the ThingTagRepository.DeleteByTagID method")
+	}
+
+	if len(mmDeleteByTagID.expectations) > 0 {
+		mmDeleteByTagID.mock.t.Fatalf("Some expectations are already set for the ThingTagRepository.DeleteByTagID method")
+	}
+
+	mmDeleteByTagID.mock.funcDeleteByTagID = f
+	return mmDeleteByTagID.mock
+}
+
+// When sets expectation for the ThingTagRepository.DeleteByTagID which will trigger the result defined by the following
+// Then helper
+func (mmDeleteByTagID *mThingTagRepositoryMockDeleteByTagID) When(ctx context.Context, tagID int, tx *sql.Tx) *ThingTagRepositoryMockDeleteByTagIDExpectation {
+	if mmDeleteByTagID.mock.funcDeleteByTagID != nil {
+		mmDeleteByTagID.mock.t.Fatalf("ThingTagRepositoryMock.DeleteByTagID mock is already set by Set")
+	}
+
+	expectation := &ThingTagRepositoryMockDeleteByTagIDExpectation{
+		mock:   mmDeleteByTagID.mock,
+		params: &ThingTagRepositoryMockDeleteByTagIDParams{ctx, tagID, tx},
+	}
+	mmDeleteByTagID.expectations = append(mmDeleteByTagID.expectations, expectation)
+	return expectation
+}
+
+// Then sets up ThingTagRepository.DeleteByTagID return parameters for the expectation previously defined by the When method
+func (e *ThingTagRepositoryMockDeleteByTagIDExpectation) Then(err error) *ThingTagRepositoryMock {
+	e.results = &ThingTagRepositoryMockDeleteByTagIDResults{err}
+	return e.mock
+}
+
+// Times sets number of times ThingTagRepository.DeleteByTagID should be invoked
+func (mmDeleteByTagID *mThingTagRepositoryMockDeleteByTagID) Times(n uint64) *mThingTagRepositoryMockDeleteByTagID {
+	if n == 0 {
+		mmDeleteByTagID.mock.t.Fatalf("Times of ThingTagRepositoryMock.DeleteByTagID mock can not be zero")
+	}
+	mm_atomic.StoreUint64(&mmDeleteByTagID.expectedInvocations, n)
+	return mmDeleteByTagID
+}
+
+func (mmDeleteByTagID *mThingTagRepositoryMockDeleteByTagID) invocationsDone() bool {
+	if len(mmDeleteByTagID.expectations) == 0 && mmDeleteByTagID.defaultExpectation == nil && mmDeleteByTagID.mock.funcDeleteByTagID == nil {
+		return true
+	}
+
+	totalInvocations := mm_atomic.LoadUint64(&mmDeleteByTagID.mock.afterDeleteByTagIDCounter)
+	expectedInvocations := mm_atomic.LoadUint64(&mmDeleteByTagID.expectedInvocations)
+
+	return totalInvocations > 0 && (expectedInvocations == 0 || expectedInvocations == totalInvocations)
+}
+
+// DeleteByTagID implements tag.ThingTagRepository
+func (mmDeleteByTagID *ThingTagRepositoryMock) DeleteByTagID(ctx context.Context, tagID int, tx *sql.Tx) (err error) {
+	mm_atomic.AddUint64(&mmDeleteByTagID.beforeDeleteByTagIDCounter, 1)
+	defer mm_atomic.AddUint64(&mmDeleteByTagID.afterDeleteByTagIDCounter, 1)
+
+	if mmDeleteByTagID.inspectFuncDeleteByTagID != nil {
+		mmDeleteByTagID.inspectFuncDeleteByTagID(ctx, tagID, tx)
+	}
+
+	mm_params := ThingTagRepositoryMockDeleteByTagIDParams{ctx, tagID, tx}
+
+	// Record call args
+	mmDeleteByTagID.DeleteByTagIDMock.mutex.Lock()
+	mmDeleteByTagID.DeleteByTagIDMock.callArgs = append(mmDeleteByTagID.DeleteByTagIDMock.callArgs, &mm_params)
+	mmDeleteByTagID.DeleteByTagIDMock.mutex.Unlock()
+
+	for _, e := range mmDeleteByTagID.DeleteByTagIDMock.expectations {
+		if minimock.Equal(*e.params, mm_params) {
+			mm_atomic.AddUint64(&e.Counter, 1)
+			return e.results.err
+		}
+	}
+
+	if mmDeleteByTagID.DeleteByTagIDMock.defaultExpectation != nil {
+		mm_atomic.AddUint64(&mmDeleteByTagID.DeleteByTagIDMock.defaultExpectation.Counter, 1)
+		mm_want := mmDeleteByTagID.DeleteByTagIDMock.defaultExpectation.params
+		mm_want_ptrs := mmDeleteByTagID.DeleteByTagIDMock.defaultExpectation.paramPtrs
+
+		mm_got := ThingTagRepositoryMockDeleteByTagIDParams{ctx, tagID, tx}
+
+		if mm_want_ptrs != nil {
+
+			if mm_want_ptrs.ctx != nil && !minimock.Equal(*mm_want_ptrs.ctx, mm_got.ctx) {
+				mmDeleteByTagID.t.Errorf("ThingTagRepositoryMock.DeleteByTagID got unexpected parameter ctx, want: %#v, got: %#v%s\n", *mm_want_ptrs.ctx, mm_got.ctx, minimock.Diff(*mm_want_ptrs.ctx, mm_got.ctx))
+			}
+
+			if mm_want_ptrs.tagID != nil && !minimock.Equal(*mm_want_ptrs.tagID, mm_got.tagID) {
+				mmDeleteByTagID.t.Errorf("ThingTagRepositoryMock.DeleteByTagID got unexpected parameter tagID, want: %#v, got: %#v%s\n", *mm_want_ptrs.tagID, mm_got.tagID, minimock.Diff(*mm_want_ptrs.tagID, mm_got.tagID))
+			}
+
+			if mm_want_ptrs.tx != nil && !minimock.Equal(*mm_want_ptrs.tx, mm_got.tx) {
+				mmDeleteByTagID.t.Errorf("ThingTagRepositoryMock.DeleteByTagID got unexpected parameter tx, want: %#v, got: %#v%s\n", *mm_want_ptrs.tx, mm_got.tx, minimock.Diff(*mm_want_ptrs.tx, mm_got.tx))
+			}
+
+		} else if mm_want != nil && !minimock.Equal(*mm_want, mm_got) {
+			mmDeleteByTagID.t.Errorf("ThingTagRepositoryMock.DeleteByTagID got unexpected parameters, want: %#v, got: %#v%s\n", *mm_want, mm_got, minimock.Diff(*mm_want, mm_got))
+		}
+
+		mm_results := mmDeleteByTagID.DeleteByTagIDMock.defaultExpectation.results
+		if mm_results == nil {
+			mmDeleteByTagID.t.Fatal("No results are set for the ThingTagRepositoryMock.DeleteByTagID")
+		}
+		return (*mm_results).err
+	}
+	if mmDeleteByTagID.funcDeleteByTagID != nil {
+		return mmDeleteByTagID.funcDeleteByTagID(ctx, tagID, tx)
+	}
+	mmDeleteByTagID.t.Fatalf("Unexpected call to ThingTagRepositoryMock.DeleteByTagID. %v %v %v", ctx, tagID, tx)
+	return
+}
+
+// DeleteByTagIDAfterCounter returns a count of finished ThingTagRepositoryMock.DeleteByTagID invocations
+func (mmDeleteByTagID *ThingTagRepositoryMock) DeleteByTagIDAfterCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmDeleteByTagID.afterDeleteByTagIDCounter)
+}
+
+// DeleteByTagIDBeforeCounter returns a count of ThingTagRepositoryMock.DeleteByTagID invocations
+func (mmDeleteByTagID *ThingTagRepositoryMock) DeleteByTagIDBeforeCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmDeleteByTagID.beforeDeleteByTagIDCounter)
+}
+
+// Calls returns a list of arguments used in each call to ThingTagRepositoryMock.DeleteByTagID.
+// The list is in the same order as the calls were made (i.e. recent calls have a higher index)
+func (mmDeleteByTagID *mThingTagRepositoryMockDeleteByTagID) Calls() []*ThingTagRepositoryMockDeleteByTagIDParams {
+	mmDeleteByTagID.mutex.RLock()
+
+	argCopy := make([]*ThingTagRepositoryMockDeleteByTagIDParams, len(mmDeleteByTagID.callArgs))
+	copy(argCopy, mmDeleteByTagID.callArgs)
+
+	mmDeleteByTagID.mutex.RUnlock()
+
+	return argCopy
+}
+
+// MinimockDeleteByTagIDDone returns true if the count of the DeleteByTagID invocations corresponds
+// the number of defined expectations
+func (m *ThingTagRepositoryMock) MinimockDeleteByTagIDDone() bool {
+	if m.DeleteByTagIDMock.optional {
+		// Optional methods provide '0 or more' call count restriction.
+		return true
+	}
+
+	for _, e := range m.DeleteByTagIDMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			return false
+		}
+	}
+
+	return m.DeleteByTagIDMock.invocationsDone()
+}
+
+// MinimockDeleteByTagIDInspect logs each unmet expectation
+func (m *ThingTagRepositoryMock) MinimockDeleteByTagIDInspect() {
+	for _, e := range m.DeleteByTagIDMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			m.t.Errorf("Expected call to ThingTagRepositoryMock.DeleteByTagID with params: %#v", *e.params)
+		}
+	}
+
+	afterDeleteByTagIDCounter := mm_atomic.LoadUint64(&m.afterDeleteByTagIDCounter)
+	// if default expectation was set then invocations count should be greater than zero
+	if m.DeleteByTagIDMock.defaultExpectation != nil && afterDeleteByTagIDCounter < 1 {
+		if m.DeleteByTagIDMock.defaultExpectation.params == nil {
+			m.t.Error("Expected call to ThingTagRepositoryMock.DeleteByTagID")
+		} else {
+			m.t.Errorf("Expected call to ThingTagRepositoryMock.DeleteByTagID with params: %#v", *m.DeleteByTagIDMock.defaultExpectation.params)
+		}
+	}
+	// if func was set then invocations count should be greater than zero
+	if m.funcDeleteByTagID != nil && afterDeleteByTagIDCounter < 1 {
+		m.t.Error("Expected call to ThingTagRepositoryMock.DeleteByTagID")
+	}
+
+	if !m.DeleteByTagIDMock.invocationsDone() && afterDeleteByTagIDCounter > 0 {
+		m.t.Errorf("Expected %d calls to ThingTagRepositoryMock.DeleteByTagID but found %d calls",
+			mm_atomic.LoadUint64(&m.DeleteByTagIDMock.expectedInvocations), afterDeleteByTagIDCounter)
+	}
+}
+
+// MinimockFinish checks that all mocked methods have been called the expected number of times
+func (m *ThingTagRepositoryMock) MinimockFinish() {
+	m.finishOnce.Do(func() {
+		if !m.minimockDone() {
+			m.MinimockAddInspect()
+
+			m.MinimockDeleteInspect()
+
+			m.MinimockDeleteByTagIDInspect()
+		}
+	})
+}
+
+// MinimockWait waits for all mocked methods to be called the expected number of times
+func (m *ThingTagRepositoryMock) MinimockWait(timeout mm_time.Duration) {
+	timeoutCh := mm_time.After(timeout)
+	for {
+		if m.minimockDone() {
+			return
+		}
+		select {
+		case <-timeoutCh:
+			m.MinimockFinish()
+			return
+		case <-mm_time.After(10 * mm_time.Millisecond):
+		}
+	}
+}
+
+func (m *ThingTagRepositoryMock) minimockDone() bool {
+	done := true
+	return done &&
+		m.MinimockAddDone() &&
+		m.MinimockDeleteDone() &&
+		m.MinimockDeleteByTagIDDone()
+}

+ 7 - 7
internal/api/v1/tag/update_tag.go

@@ -1,13 +1,13 @@
 package tag
 
 import (
+	"github.com/go-playground/validator/v10"
+	"github.com/gofiber/fiber/v2"
+
 	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/factory"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/mappers"
-	"github.com/go-playground/validator/v10"
-	"github.com/gofiber/fiber/v2"
 )
 
 // @Router 		/api/v1/tags/{tagId} [put]
@@ -21,7 +21,7 @@ import (
 // @security 	APIKey
 // @Accept      json
 // @Produce     json
-func UpdateTagHandler(sp interfaces.ServiceProvider) fiber.Handler {
+func UpdateTagHandler(tagRepository TagRepository) fiber.Handler {
 	return func(fctx *fiber.Ctx) error {
 		ctx := fctx.Context()
 		id, err := fctx.ParamsInt("tagId")
@@ -39,18 +39,18 @@ func UpdateTagHandler(sp interfaces.ServiceProvider) fiber.Handler {
 			return fctx.Status(fiber.StatusBadRequest).JSON(factory.CreateValidateErrorResponse(err))
 		}
 
-		err = sp.GetTagRepository().Update(ctx, mappers.ConvertToUpdateTagRequestModel(id, req), nil)
+		err = tagRepository.Update(ctx, mappers.ToUpdateTagRequest(id, req), nil)
 		if err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
-		res, err := sp.GetTagRepository().Get(ctx, id)
+		res, err := tagRepository.Get(ctx, id)
 		if err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
 		res = helpers.ApplyLocation(fctx, res)
 
-		return fctx.JSON(mappers.ConvertToTagResponseDTO(*res))
+		return fctx.JSON(mappers.ToTagResponse(*res))
 	}
 }

+ 28 - 27
internal/api/v1/tag/update_tag_test.go

@@ -8,20 +8,21 @@ import (
 	"strconv"
 	"testing"
 
-	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
-	repoMocks "git.dmitriygnatenko.ru/dima/homethings/internal/repositories/mocks"
-	sp "git.dmitriygnatenko.ru/dima/homethings/internal/service_provider"
 	"github.com/brianvoe/gofakeit/v6"
 	"github.com/gofiber/fiber/v2"
 	"github.com/gojuno/minimock/v3"
 	"github.com/stretchr/testify/assert"
+
+	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/tag/mocks"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
 )
 
-func Test_UpdateTagHandler(t *testing.T) {
+func TestUpdateTagHandler(t *testing.T) {
+	t.Parallel()
+
 	type req struct {
 		method      string
 		route       string
@@ -30,7 +31,6 @@ func Test_UpdateTagHandler(t *testing.T) {
 	}
 
 	var (
-		mc        = minimock.NewController(t)
 		tagID     = gofakeit.Number(1, 1000)
 		title     = gofakeit.Phrase()
 		style     = gofakeit.Phrase()
@@ -69,15 +69,15 @@ func Test_UpdateTagHandler(t *testing.T) {
 		req         req
 		resCode     int
 		resBody     interface{}
-		tagRepoMock func(mc *minimock.Controller) interfaces.TagRepository
+		tagRepoMock func(mc *minimock.Controller) TagRepository
 	}{
 		{
 			name:    "positive case",
 			req:     correctReq,
 			resCode: fiber.StatusOK,
 			resBody: expectedRes,
-			tagRepoMock: func(mc *minimock.Controller) interfaces.TagRepository {
-				mock := repoMocks.NewTagRepositoryMock(mc)
+			tagRepoMock: func(mc *minimock.Controller) TagRepository {
+				mock := mocks.NewTagRepositoryMock(mc)
 
 				mock.UpdateMock.Inspect(func(ctx context.Context, req models.UpdateTagRequest, tx *sql.Tx) {
 					assert.Equal(mc, tagID, req.ID)
@@ -99,8 +99,8 @@ func Test_UpdateTagHandler(t *testing.T) {
 				route:  "/v1/tags/" + gofakeit.Word(),
 			},
 			resCode: fiber.StatusBadRequest,
-			tagRepoMock: func(mc *minimock.Controller) interfaces.TagRepository {
-				return repoMocks.NewTagRepositoryMock(mc)
+			tagRepoMock: func(mc *minimock.Controller) TagRepository {
+				return mocks.NewTagRepositoryMock(mc)
 			},
 		},
 		{
@@ -110,8 +110,8 @@ func Test_UpdateTagHandler(t *testing.T) {
 				route:  "/v1/tags/" + strconv.Itoa(tagID),
 			},
 			resCode: fiber.StatusBadRequest,
-			tagRepoMock: func(mc *minimock.Controller) interfaces.TagRepository {
-				return repoMocks.NewTagRepositoryMock(mc)
+			tagRepoMock: func(mc *minimock.Controller) TagRepository {
+				return mocks.NewTagRepositoryMock(mc)
 			},
 		},
 		{
@@ -131,8 +131,8 @@ func Test_UpdateTagHandler(t *testing.T) {
 					Tag:   "required",
 				},
 			},
-			tagRepoMock: func(mc *minimock.Controller) interfaces.TagRepository {
-				return repoMocks.NewTagRepositoryMock(mc)
+			tagRepoMock: func(mc *minimock.Controller) TagRepository {
+				return mocks.NewTagRepositoryMock(mc)
 			},
 		},
 		{
@@ -152,16 +152,16 @@ func Test_UpdateTagHandler(t *testing.T) {
 					Tag:   "required",
 				},
 			},
-			tagRepoMock: func(mc *minimock.Controller) interfaces.TagRepository {
-				return repoMocks.NewTagRepositoryMock(mc)
+			tagRepoMock: func(mc *minimock.Controller) TagRepository {
+				return mocks.NewTagRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - repository error (update)",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			tagRepoMock: func(mc *minimock.Controller) interfaces.TagRepository {
-				mock := repoMocks.NewTagRepositoryMock(mc)
+			tagRepoMock: func(mc *minimock.Controller) TagRepository {
+				mock := mocks.NewTagRepositoryMock(mc)
 
 				mock.UpdateMock.Inspect(func(ctx context.Context, req models.UpdateTagRequest, tx *sql.Tx) {
 					assert.Equal(mc, tagID, req.ID)
@@ -176,8 +176,8 @@ func Test_UpdateTagHandler(t *testing.T) {
 			name:    "negative case - repository error (get)",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			tagRepoMock: func(mc *minimock.Controller) interfaces.TagRepository {
-				mock := repoMocks.NewTagRepositoryMock(mc)
+			tagRepoMock: func(mc *minimock.Controller) TagRepository {
+				mock := mocks.NewTagRepositoryMock(mc)
 
 				mock.UpdateMock.Inspect(func(ctx context.Context, req models.UpdateTagRequest, tx *sql.Tx) {
 					assert.Equal(mc, tagID, req.ID)
@@ -196,10 +196,11 @@ func Test_UpdateTagHandler(t *testing.T) {
 
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			fiberApp := fiber.New()
-			serviceProvider := sp.InitMock(tt.tagRepoMock(mc))
+			t.Parallel()
 
-			fiberApp.Put("/v1/tags/:tagId", UpdateTagHandler(serviceProvider))
+			mc := minimock.NewController(t)
+			fiberApp := fiber.New()
+			fiberApp.Put("/v1/tags/:tagId", UpdateTagHandler(tt.tagRepoMock(mc)))
 
 			fiberReq := httptest.NewRequest(tt.req.method, tt.req.route, helpers.ConvertDataToIOReader(tt.req.body))
 			fiberReq.Header.Add(fiber.HeaderContentType, tt.req.contentType)

+ 58 - 8
internal/api/v1/thing/add_thing.go

@@ -1,16 +1,63 @@
 package thing
 
+//go:generate mkdir -p mocks
+//go:generate rm -rf ./mocks/*_minimock.go
+//go:generate minimock -i ThingRepository,PlaceThingRepository,ThingTagRepository,ThingImageRepository,ThingNotificationRepository,FileRepository -o ./mocks/ -s "_minimock.go"
+
 import (
+	"context"
+	"database/sql"
+
 	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/factory"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/mappers"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
+
 	"github.com/go-playground/validator/v10"
 	"github.com/gofiber/fiber/v2"
 )
 
+type (
+	ThingRepository interface {
+		Get(ctx context.Context, thingID int) (*models.Thing, error)
+		Search(ctx context.Context, search string) ([]models.Thing, error)
+		GetByPlaceID(ctx context.Context, placeID int) ([]models.Thing, error)
+		GetAllByPlaceID(ctx context.Context, placeID int) ([]models.Thing, error)
+		Add(ctx context.Context, req models.AddThingRequest, tx *sql.Tx) (int, error)
+		Update(ctx context.Context, req models.UpdateThingRequest, tx *sql.Tx) error
+		Delete(ctx context.Context, thingID int, tx *sql.Tx) error
+		BeginTx(ctx context.Context, level sql.IsolationLevel) (*sql.Tx, error)
+		CommitTx(tx *sql.Tx) error
+	}
+
+	PlaceThingRepository interface {
+		Add(ctx context.Context, req models.AddPlaceThingRequest, tx *sql.Tx) error
+		GetByThingID(ctx context.Context, thingID int) (*models.PlaceThing, error)
+		UpdatePlace(ctx context.Context, req models.UpdatePlaceThingRequest, tx *sql.Tx) error
+		DeleteThing(ctx context.Context, thingID int, tx *sql.Tx) error
+	}
+
+	ThingTagRepository interface {
+		GetByPlaceID(ctx context.Context, placeID int) ([]models.ThingTag, error)
+		DeleteByThingID(ctx context.Context, thingID int, tx *sql.Tx) error
+	}
+
+	ThingImageRepository interface {
+		GetByThingID(ctx context.Context, thingID int) ([]models.Image, error)
+		Delete(ctx context.Context, imageID int, tx *sql.Tx) error
+	}
+
+	ThingNotificationRepository interface {
+		Delete(ctx context.Context, thingID int, tx *sql.Tx) error
+	}
+
+	FileRepository interface {
+		Delete(path string) error
+	}
+)
+
 // @Router 		/api/v1/things [post]
 // @Param       data body dto.AddThingRequest true "Request body"
 // @Success     200 {object} dto.ThingResponse
@@ -21,7 +68,10 @@ import (
 // @security 	APIKey
 // @Accept      json
 // @Produce     json
-func AddThingHandler(sp interfaces.ServiceProvider) fiber.Handler {
+func AddThingHandler(
+	thingRepository ThingRepository,
+	placeThingRepository PlaceThingRepository,
+) fiber.Handler {
 	return func(fctx *fiber.Ctx) error {
 		ctx := fctx.Context()
 		req := dto.AddThingRequest{}
@@ -34,32 +84,32 @@ func AddThingHandler(sp interfaces.ServiceProvider) fiber.Handler {
 			return fctx.Status(fiber.StatusBadRequest).JSON(factory.CreateValidateErrorResponse(err))
 		}
 
-		tx, err := sp.GetThingRepository().BeginTx(ctx, API.DefaultTxLevel)
+		tx, err := thingRepository.BeginTx(ctx, API.DefaultTxLevel)
 		if err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
-		id, err := sp.GetThingRepository().Add(ctx, mappers.ConvertToAddThingRequestModel(req), tx)
+		id, err := thingRepository.Add(ctx, mappers.ToAddThingRequest(req), tx)
 		if err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
-		err = sp.GetPlaceThingRepository().Add(ctx, mappers.ConvertToAddPlaceThingRequestModel(id, req.PlaceID), tx)
+		err = placeThingRepository.Add(ctx, mappers.ToAddPlaceThingRequest(id, req.PlaceID), tx)
 		if err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
-		if err = sp.GetThingRepository().CommitTx(tx); err != nil {
+		if err = thingRepository.CommitTx(tx); err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
-		res, err := sp.GetThingRepository().Get(ctx, id)
+		res, err := thingRepository.Get(ctx, id)
 		if err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
 		res = helpers.ApplyLocation(fctx, res)
 
-		return fctx.JSON(mappers.ConvertToThingResponseDTO(*res))
+		return fctx.JSON(mappers.ToThingResponse(*res))
 	}
 }

+ 51 - 50
internal/api/v1/thing/add_thing_test.go

@@ -7,20 +7,21 @@ import (
 	"net/http/httptest"
 	"testing"
 
-	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
-	repoMocks "git.dmitriygnatenko.ru/dima/homethings/internal/repositories/mocks"
-	sp "git.dmitriygnatenko.ru/dima/homethings/internal/service_provider"
 	"github.com/brianvoe/gofakeit/v6"
 	"github.com/gofiber/fiber/v2"
 	"github.com/gojuno/minimock/v3"
 	"github.com/stretchr/testify/assert"
+
+	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/thing/mocks"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
 )
 
-func Test_AddThingHandler(t *testing.T) {
+func TestAddThingHandler(t *testing.T) {
+	t.Parallel()
+
 	type req struct {
 		method      string
 		route       string
@@ -29,7 +30,6 @@ func Test_AddThingHandler(t *testing.T) {
 	}
 
 	var (
-		mc          = minimock.NewController(t)
 		placeID     = gofakeit.Number(1, 1000)
 		thingID     = gofakeit.Number(1, 1000)
 		title       = gofakeit.Phrase()
@@ -72,16 +72,16 @@ func Test_AddThingHandler(t *testing.T) {
 		req                req
 		resCode            int
 		resBody            interface{}
-		thingRepoMock      func(mc *minimock.Controller) interfaces.ThingRepository
-		placeThingRepoMock func(mc *minimock.Controller) interfaces.PlaceThingRepository
+		thingRepoMock      func(mc *minimock.Controller) ThingRepository
+		placeThingRepoMock func(mc *minimock.Controller) PlaceThingRepository
 	}{
 		{
 			name:    "positive case",
 			req:     correctReq,
 			resCode: fiber.StatusOK,
 			resBody: expectedRes,
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				mock := repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				mock := mocks.NewThingRepositoryMock(mc)
 
 				mock.BeginTxMock.Return(nil, nil)
 
@@ -98,8 +98,8 @@ func Test_AddThingHandler(t *testing.T) {
 
 				return mock
 			},
-			placeThingRepoMock: func(mc *minimock.Controller) interfaces.PlaceThingRepository {
-				mock := repoMocks.NewPlaceThingRepositoryMock(mc)
+			placeThingRepoMock: func(mc *minimock.Controller) PlaceThingRepository {
+				mock := mocks.NewPlaceThingRepositoryMock(mc)
 
 				mock.AddMock.Inspect(func(ctx context.Context, req models.AddPlaceThingRequest, tx *sql.Tx) {
 					assert.Equal(mc, thingID, req.ThingID)
@@ -116,11 +116,11 @@ func Test_AddThingHandler(t *testing.T) {
 				route:  "/v1/things",
 			},
 			resCode: fiber.StatusBadRequest,
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				return repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				return mocks.NewThingRepositoryMock(mc)
 			},
-			placeThingRepoMock: func(mc *minimock.Controller) interfaces.PlaceThingRepository {
-				return repoMocks.NewPlaceThingRepositoryMock(mc)
+			placeThingRepoMock: func(mc *minimock.Controller) PlaceThingRepository {
+				return mocks.NewPlaceThingRepositoryMock(mc)
 			},
 		},
 		{
@@ -141,11 +141,11 @@ func Test_AddThingHandler(t *testing.T) {
 					Tag:   "required",
 				},
 			},
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				return repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				return mocks.NewThingRepositoryMock(mc)
 			},
-			placeThingRepoMock: func(mc *minimock.Controller) interfaces.PlaceThingRepository {
-				return repoMocks.NewPlaceThingRepositoryMock(mc)
+			placeThingRepoMock: func(mc *minimock.Controller) PlaceThingRepository {
+				return mocks.NewPlaceThingRepositoryMock(mc)
 			},
 		},
 		{
@@ -166,32 +166,32 @@ func Test_AddThingHandler(t *testing.T) {
 					Tag:   "required",
 				},
 			},
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				return repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				return mocks.NewThingRepositoryMock(mc)
 			},
-			placeThingRepoMock: func(mc *minimock.Controller) interfaces.PlaceThingRepository {
-				return repoMocks.NewPlaceThingRepositoryMock(mc)
+			placeThingRepoMock: func(mc *minimock.Controller) PlaceThingRepository {
+				return mocks.NewPlaceThingRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - repository error (begin tx)",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				mock := repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				mock := mocks.NewThingRepositoryMock(mc)
 				mock.BeginTxMock.Return(nil, testError)
 				return mock
 			},
-			placeThingRepoMock: func(mc *minimock.Controller) interfaces.PlaceThingRepository {
-				return repoMocks.NewPlaceThingRepositoryMock(mc)
+			placeThingRepoMock: func(mc *minimock.Controller) PlaceThingRepository {
+				return mocks.NewPlaceThingRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - repository error (add thing)",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				mock := repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				mock := mocks.NewThingRepositoryMock(mc)
 
 				mock.BeginTxMock.Return(nil, nil)
 
@@ -202,16 +202,16 @@ func Test_AddThingHandler(t *testing.T) {
 
 				return mock
 			},
-			placeThingRepoMock: func(mc *minimock.Controller) interfaces.PlaceThingRepository {
-				return repoMocks.NewPlaceThingRepositoryMock(mc)
+			placeThingRepoMock: func(mc *minimock.Controller) PlaceThingRepository {
+				return mocks.NewPlaceThingRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - repository error (add place thing)",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				mock := repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				mock := mocks.NewThingRepositoryMock(mc)
 
 				mock.BeginTxMock.Return(nil, nil)
 
@@ -222,8 +222,8 @@ func Test_AddThingHandler(t *testing.T) {
 
 				return mock
 			},
-			placeThingRepoMock: func(mc *minimock.Controller) interfaces.PlaceThingRepository {
-				mock := repoMocks.NewPlaceThingRepositoryMock(mc)
+			placeThingRepoMock: func(mc *minimock.Controller) PlaceThingRepository {
+				mock := mocks.NewPlaceThingRepositoryMock(mc)
 
 				mock.AddMock.Inspect(func(ctx context.Context, req models.AddPlaceThingRequest, tx *sql.Tx) {
 					assert.Equal(mc, thingID, req.ThingID)
@@ -237,8 +237,8 @@ func Test_AddThingHandler(t *testing.T) {
 			name:    "negative case - repository error (commit tx)",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				mock := repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				mock := mocks.NewThingRepositoryMock(mc)
 
 				mock.BeginTxMock.Return(nil, nil)
 
@@ -251,8 +251,8 @@ func Test_AddThingHandler(t *testing.T) {
 
 				return mock
 			},
-			placeThingRepoMock: func(mc *minimock.Controller) interfaces.PlaceThingRepository {
-				mock := repoMocks.NewPlaceThingRepositoryMock(mc)
+			placeThingRepoMock: func(mc *minimock.Controller) PlaceThingRepository {
+				mock := mocks.NewPlaceThingRepositoryMock(mc)
 
 				mock.AddMock.Inspect(func(ctx context.Context, req models.AddPlaceThingRequest, tx *sql.Tx) {
 					assert.Equal(mc, thingID, req.ThingID)
@@ -266,8 +266,8 @@ func Test_AddThingHandler(t *testing.T) {
 			name:    "negative case - repository error (get thing)",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				mock := repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				mock := mocks.NewThingRepositoryMock(mc)
 
 				mock.BeginTxMock.Return(nil, nil)
 
@@ -284,8 +284,8 @@ func Test_AddThingHandler(t *testing.T) {
 
 				return mock
 			},
-			placeThingRepoMock: func(mc *minimock.Controller) interfaces.PlaceThingRepository {
-				mock := repoMocks.NewPlaceThingRepositoryMock(mc)
+			placeThingRepoMock: func(mc *minimock.Controller) PlaceThingRepository {
+				mock := mocks.NewPlaceThingRepositoryMock(mc)
 
 				mock.AddMock.Inspect(func(ctx context.Context, req models.AddPlaceThingRequest, tx *sql.Tx) {
 					assert.Equal(mc, thingID, req.ThingID)
@@ -299,10 +299,11 @@ func Test_AddThingHandler(t *testing.T) {
 
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			fiberApp := fiber.New()
-			serviceProvider := sp.InitMock(tt.thingRepoMock(mc), tt.placeThingRepoMock(mc))
+			t.Parallel()
 
-			fiberApp.Post("/v1/things", AddThingHandler(serviceProvider))
+			mc := minimock.NewController(t)
+			fiberApp := fiber.New()
+			fiberApp.Post("/v1/things", AddThingHandler(tt.thingRepoMock(mc), tt.placeThingRepoMock(mc)))
 
 			fiberReq := httptest.NewRequest(tt.req.method, tt.req.route, helpers.ConvertDataToIOReader(tt.req.body))
 			fiberReq.Header.Add(fiber.HeaderContentType, tt.req.contentType)

+ 22 - 14
internal/api/v1/thing/delete_thing.go

@@ -2,11 +2,12 @@ package thing
 
 import (
 	"database/sql"
+	"errors"
+
+	"github.com/gofiber/fiber/v2"
 
 	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/factory"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
-	"github.com/gofiber/fiber/v2"
 )
 
 // @Router 		/api/v1/things/{thingId} [delete]
@@ -19,7 +20,14 @@ import (
 // @security 	APIKey
 // @Accept      json
 // @Produce     json
-func DeleteThingHandler(sp interfaces.ServiceProvider) fiber.Handler {
+func DeleteThingHandler(
+	thingRepository ThingRepository,
+	thingTagRepository ThingTagRepository,
+	placeThingRepository PlaceThingRepository,
+	thingImageRepository ThingImageRepository,
+	thingNotificationRepository ThingNotificationRepository,
+	fileRepository FileRepository,
+) fiber.Handler {
 	return func(fctx *fiber.Ctx) error {
 		ctx := fctx.Context()
 		id, err := fctx.ParamsInt("thingId")
@@ -27,23 +35,23 @@ func DeleteThingHandler(sp interfaces.ServiceProvider) fiber.Handler {
 			return fiber.NewError(fiber.StatusBadRequest, err.Error())
 		}
 
-		if _, err = sp.GetThingRepository().Get(ctx, id); err != nil {
-			if err == sql.ErrNoRows {
+		if _, err = thingRepository.Get(ctx, id); err != nil {
+			if errors.Is(err, sql.ErrNoRows) {
 				return fiber.NewError(fiber.StatusBadRequest, "")
 			}
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
-		tx, err := sp.GetThingRepository().BeginTx(ctx, API.DefaultTxLevel)
+		tx, err := thingRepository.BeginTx(ctx, API.DefaultTxLevel)
 		if err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
-		if err = sp.GetPlaceThingRepository().DeleteThing(ctx, id, tx); err != nil {
+		if err = placeThingRepository.DeleteThing(ctx, id, tx); err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
-		images, err := sp.GetThingImageRepository().GetByThingID(ctx, id)
+		images, err := thingImageRepository.GetByThingID(ctx, id)
 		if err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
@@ -52,30 +60,30 @@ func DeleteThingHandler(sp interfaces.ServiceProvider) fiber.Handler {
 		for i := range images {
 			imageURLs = append(imageURLs, images[i].Image)
 
-			if err = sp.GetThingImageRepository().Delete(ctx, images[i].ID, tx); err != nil {
+			if err = thingImageRepository.Delete(ctx, images[i].ID, tx); err != nil {
 				return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 			}
 		}
 
-		if err = sp.GetThingTagRepository().DeleteByThingID(ctx, id, tx); err != nil {
+		if err = thingTagRepository.DeleteByThingID(ctx, id, tx); err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
-		if err = sp.GetThingNotificationRepository().Delete(ctx, id, tx); err != nil {
+		if err = thingNotificationRepository.Delete(ctx, id, tx); err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
-		if err = sp.GetThingRepository().Delete(ctx, id, tx); err != nil {
+		if err = thingRepository.Delete(ctx, id, tx); err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
-		if err = sp.GetThingRepository().CommitTx(tx); err != nil {
+		if err = thingRepository.CommitTx(tx); err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
 		if len(imageURLs) > 0 {
 			for i := range imageURLs {
-				if err = sp.GetFileRepository().Delete(imageURLs[i]); err != nil {
+				if err = fileRepository.Delete(imageURLs[i]); err != nil {
 					return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 				}
 			}

+ 178 - 176
internal/api/v1/thing/delete_thing_test.go

@@ -8,27 +8,27 @@ import (
 	"strconv"
 	"testing"
 
-	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
-	repoMocks "git.dmitriygnatenko.ru/dima/homethings/internal/repositories/mocks"
-	sp "git.dmitriygnatenko.ru/dima/homethings/internal/service_provider"
 	"github.com/brianvoe/gofakeit/v6"
 	"github.com/gofiber/fiber/v2"
 	"github.com/gojuno/minimock/v3"
 	"github.com/stretchr/testify/assert"
+
+	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/thing/mocks"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
 )
 
-func Test_DeleteThingHandler(t *testing.T) {
+func TestDeleteThingHandler(t *testing.T) {
+	t.Parallel()
+
 	type req struct {
 		method string
 		route  string
 	}
 
 	var (
-		mc        = minimock.NewController(t)
 		thingID   = gofakeit.Number(1, 1000)
 		imageID   = gofakeit.Number(1, 1000)
 		imageURL  = gofakeit.URL()
@@ -52,12 +52,12 @@ func Test_DeleteThingHandler(t *testing.T) {
 		req                       req
 		resCode                   int
 		resBody                   interface{}
-		thingRepoMock             func(mc *minimock.Controller) interfaces.ThingRepository
-		placeThingRepoMock        func(mc *minimock.Controller) interfaces.PlaceThingRepository
-		thingImageRepoMock        func(mc *minimock.Controller) interfaces.ThingImageRepository
-		thingTagRepoMock          func(mc *minimock.Controller) interfaces.ThingTagRepository
-		thingNotificationRepoMock func(mc *minimock.Controller) interfaces.ThingNotificationRepository
-		fileRepoMock              func(mc *minimock.Controller) interfaces.FileRepository
+		thingRepoMock             func(mc *minimock.Controller) ThingRepository
+		placeThingRepoMock        func(mc *minimock.Controller) PlaceThingRepository
+		thingImageRepoMock        func(mc *minimock.Controller) ThingImageRepository
+		thingTagRepoMock          func(mc *minimock.Controller) ThingTagRepository
+		thingNotificationRepoMock func(mc *minimock.Controller) ThingNotificationRepository
+		fileRepoMock              func(mc *minimock.Controller) FileRepository
 	}{
 		{
 			name: "negative case - bad request",
@@ -66,31 +66,31 @@ func Test_DeleteThingHandler(t *testing.T) {
 				route:  "/v1/things/" + gofakeit.Word(),
 			},
 			resCode: fiber.StatusBadRequest,
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				return repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				return mocks.NewThingRepositoryMock(mc)
 			},
-			placeThingRepoMock: func(mc *minimock.Controller) interfaces.PlaceThingRepository {
-				return repoMocks.NewPlaceThingRepositoryMock(mc)
+			placeThingRepoMock: func(mc *minimock.Controller) PlaceThingRepository {
+				return mocks.NewPlaceThingRepositoryMock(mc)
 			},
-			thingImageRepoMock: func(mc *minimock.Controller) interfaces.ThingImageRepository {
-				return repoMocks.NewThingImageRepositoryMock(mc)
+			thingImageRepoMock: func(mc *minimock.Controller) ThingImageRepository {
+				return mocks.NewThingImageRepositoryMock(mc)
 			},
-			thingTagRepoMock: func(mc *minimock.Controller) interfaces.ThingTagRepository {
-				return repoMocks.NewThingTagRepositoryMock(mc)
+			thingTagRepoMock: func(mc *minimock.Controller) ThingTagRepository {
+				return mocks.NewThingTagRepositoryMock(mc)
 			},
-			thingNotificationRepoMock: func(mc *minimock.Controller) interfaces.ThingNotificationRepository {
-				return repoMocks.NewThingNotificationRepositoryMock(mc)
+			thingNotificationRepoMock: func(mc *minimock.Controller) ThingNotificationRepository {
+				return mocks.NewThingNotificationRepositoryMock(mc)
 			},
-			fileRepoMock: func(mc *minimock.Controller) interfaces.FileRepository {
-				return repoMocks.NewFileRepositoryMock(mc)
+			fileRepoMock: func(mc *minimock.Controller) FileRepository {
+				return mocks.NewFileRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - bad request (thing not found)",
 			req:     correctReq,
 			resCode: fiber.StatusBadRequest,
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				mock := repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				mock := mocks.NewThingRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -98,28 +98,28 @@ func Test_DeleteThingHandler(t *testing.T) {
 
 				return mock
 			},
-			placeThingRepoMock: func(mc *minimock.Controller) interfaces.PlaceThingRepository {
-				return repoMocks.NewPlaceThingRepositoryMock(mc)
+			placeThingRepoMock: func(mc *minimock.Controller) PlaceThingRepository {
+				return mocks.NewPlaceThingRepositoryMock(mc)
 			},
-			thingImageRepoMock: func(mc *minimock.Controller) interfaces.ThingImageRepository {
-				return repoMocks.NewThingImageRepositoryMock(mc)
+			thingImageRepoMock: func(mc *minimock.Controller) ThingImageRepository {
+				return mocks.NewThingImageRepositoryMock(mc)
 			},
-			thingTagRepoMock: func(mc *minimock.Controller) interfaces.ThingTagRepository {
-				return repoMocks.NewThingTagRepositoryMock(mc)
+			thingTagRepoMock: func(mc *minimock.Controller) ThingTagRepository {
+				return mocks.NewThingTagRepositoryMock(mc)
 			},
-			thingNotificationRepoMock: func(mc *minimock.Controller) interfaces.ThingNotificationRepository {
-				return repoMocks.NewThingNotificationRepositoryMock(mc)
+			thingNotificationRepoMock: func(mc *minimock.Controller) ThingNotificationRepository {
+				return mocks.NewThingNotificationRepositoryMock(mc)
 			},
-			fileRepoMock: func(mc *minimock.Controller) interfaces.FileRepository {
-				return repoMocks.NewFileRepositoryMock(mc)
+			fileRepoMock: func(mc *minimock.Controller) FileRepository {
+				return mocks.NewFileRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - repository error (get thing)",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				mock := repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				mock := mocks.NewThingRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -127,28 +127,28 @@ func Test_DeleteThingHandler(t *testing.T) {
 
 				return mock
 			},
-			placeThingRepoMock: func(mc *minimock.Controller) interfaces.PlaceThingRepository {
-				return repoMocks.NewPlaceThingRepositoryMock(mc)
+			placeThingRepoMock: func(mc *minimock.Controller) PlaceThingRepository {
+				return mocks.NewPlaceThingRepositoryMock(mc)
 			},
-			thingImageRepoMock: func(mc *minimock.Controller) interfaces.ThingImageRepository {
-				return repoMocks.NewThingImageRepositoryMock(mc)
+			thingImageRepoMock: func(mc *minimock.Controller) ThingImageRepository {
+				return mocks.NewThingImageRepositoryMock(mc)
 			},
-			thingTagRepoMock: func(mc *minimock.Controller) interfaces.ThingTagRepository {
-				return repoMocks.NewThingTagRepositoryMock(mc)
+			thingTagRepoMock: func(mc *minimock.Controller) ThingTagRepository {
+				return mocks.NewThingTagRepositoryMock(mc)
 			},
-			thingNotificationRepoMock: func(mc *minimock.Controller) interfaces.ThingNotificationRepository {
-				return repoMocks.NewThingNotificationRepositoryMock(mc)
+			thingNotificationRepoMock: func(mc *minimock.Controller) ThingNotificationRepository {
+				return mocks.NewThingNotificationRepositoryMock(mc)
 			},
-			fileRepoMock: func(mc *minimock.Controller) interfaces.FileRepository {
-				return repoMocks.NewFileRepositoryMock(mc)
+			fileRepoMock: func(mc *minimock.Controller) FileRepository {
+				return mocks.NewFileRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - repository error (begin tx)",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				mock := repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				mock := mocks.NewThingRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -158,28 +158,28 @@ func Test_DeleteThingHandler(t *testing.T) {
 
 				return mock
 			},
-			placeThingRepoMock: func(mc *minimock.Controller) interfaces.PlaceThingRepository {
-				return repoMocks.NewPlaceThingRepositoryMock(mc)
+			placeThingRepoMock: func(mc *minimock.Controller) PlaceThingRepository {
+				return mocks.NewPlaceThingRepositoryMock(mc)
 			},
-			thingImageRepoMock: func(mc *minimock.Controller) interfaces.ThingImageRepository {
-				return repoMocks.NewThingImageRepositoryMock(mc)
+			thingImageRepoMock: func(mc *minimock.Controller) ThingImageRepository {
+				return mocks.NewThingImageRepositoryMock(mc)
 			},
-			thingTagRepoMock: func(mc *minimock.Controller) interfaces.ThingTagRepository {
-				return repoMocks.NewThingTagRepositoryMock(mc)
+			thingTagRepoMock: func(mc *minimock.Controller) ThingTagRepository {
+				return mocks.NewThingTagRepositoryMock(mc)
 			},
-			thingNotificationRepoMock: func(mc *minimock.Controller) interfaces.ThingNotificationRepository {
-				return repoMocks.NewThingNotificationRepositoryMock(mc)
+			thingNotificationRepoMock: func(mc *minimock.Controller) ThingNotificationRepository {
+				return mocks.NewThingNotificationRepositoryMock(mc)
 			},
-			fileRepoMock: func(mc *minimock.Controller) interfaces.FileRepository {
-				return repoMocks.NewFileRepositoryMock(mc)
+			fileRepoMock: func(mc *minimock.Controller) FileRepository {
+				return mocks.NewFileRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - repository error (delete place thing)",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				mock := repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				mock := mocks.NewThingRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -189,8 +189,8 @@ func Test_DeleteThingHandler(t *testing.T) {
 
 				return mock
 			},
-			placeThingRepoMock: func(mc *minimock.Controller) interfaces.PlaceThingRepository {
-				mock := repoMocks.NewPlaceThingRepositoryMock(mc)
+			placeThingRepoMock: func(mc *minimock.Controller) PlaceThingRepository {
+				mock := mocks.NewPlaceThingRepositoryMock(mc)
 
 				mock.DeleteThingMock.Inspect(func(ctx context.Context, id int, tx *sql.Tx) {
 					assert.Equal(mc, thingID, id)
@@ -198,25 +198,25 @@ func Test_DeleteThingHandler(t *testing.T) {
 
 				return mock
 			},
-			thingImageRepoMock: func(mc *minimock.Controller) interfaces.ThingImageRepository {
-				return repoMocks.NewThingImageRepositoryMock(mc)
+			thingImageRepoMock: func(mc *minimock.Controller) ThingImageRepository {
+				return mocks.NewThingImageRepositoryMock(mc)
 			},
-			thingTagRepoMock: func(mc *minimock.Controller) interfaces.ThingTagRepository {
-				return repoMocks.NewThingTagRepositoryMock(mc)
+			thingTagRepoMock: func(mc *minimock.Controller) ThingTagRepository {
+				return mocks.NewThingTagRepositoryMock(mc)
 			},
-			thingNotificationRepoMock: func(mc *minimock.Controller) interfaces.ThingNotificationRepository {
-				return repoMocks.NewThingNotificationRepositoryMock(mc)
+			thingNotificationRepoMock: func(mc *minimock.Controller) ThingNotificationRepository {
+				return mocks.NewThingNotificationRepositoryMock(mc)
 			},
-			fileRepoMock: func(mc *minimock.Controller) interfaces.FileRepository {
-				return repoMocks.NewFileRepositoryMock(mc)
+			fileRepoMock: func(mc *minimock.Controller) FileRepository {
+				return mocks.NewFileRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - repository error (get images)",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				mock := repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				mock := mocks.NewThingRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -226,8 +226,8 @@ func Test_DeleteThingHandler(t *testing.T) {
 
 				return mock
 			},
-			placeThingRepoMock: func(mc *minimock.Controller) interfaces.PlaceThingRepository {
-				mock := repoMocks.NewPlaceThingRepositoryMock(mc)
+			placeThingRepoMock: func(mc *minimock.Controller) PlaceThingRepository {
+				mock := mocks.NewPlaceThingRepositoryMock(mc)
 
 				mock.DeleteThingMock.Inspect(func(ctx context.Context, id int, tx *sql.Tx) {
 					assert.Equal(mc, thingID, id)
@@ -235,8 +235,8 @@ func Test_DeleteThingHandler(t *testing.T) {
 
 				return mock
 			},
-			thingImageRepoMock: func(mc *minimock.Controller) interfaces.ThingImageRepository {
-				mock := repoMocks.NewThingImageRepositoryMock(mc)
+			thingImageRepoMock: func(mc *minimock.Controller) ThingImageRepository {
+				mock := mocks.NewThingImageRepositoryMock(mc)
 
 				mock.GetByThingIDMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -244,22 +244,22 @@ func Test_DeleteThingHandler(t *testing.T) {
 
 				return mock
 			},
-			thingTagRepoMock: func(mc *minimock.Controller) interfaces.ThingTagRepository {
-				return repoMocks.NewThingTagRepositoryMock(mc)
+			thingTagRepoMock: func(mc *minimock.Controller) ThingTagRepository {
+				return mocks.NewThingTagRepositoryMock(mc)
 			},
-			thingNotificationRepoMock: func(mc *minimock.Controller) interfaces.ThingNotificationRepository {
-				return repoMocks.NewThingNotificationRepositoryMock(mc)
+			thingNotificationRepoMock: func(mc *minimock.Controller) ThingNotificationRepository {
+				return mocks.NewThingNotificationRepositoryMock(mc)
 			},
-			fileRepoMock: func(mc *minimock.Controller) interfaces.FileRepository {
-				return repoMocks.NewFileRepositoryMock(mc)
+			fileRepoMock: func(mc *minimock.Controller) FileRepository {
+				return mocks.NewFileRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - repository error (delete images)",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				mock := repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				mock := mocks.NewThingRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -269,8 +269,8 @@ func Test_DeleteThingHandler(t *testing.T) {
 
 				return mock
 			},
-			placeThingRepoMock: func(mc *minimock.Controller) interfaces.PlaceThingRepository {
-				mock := repoMocks.NewPlaceThingRepositoryMock(mc)
+			placeThingRepoMock: func(mc *minimock.Controller) PlaceThingRepository {
+				mock := mocks.NewPlaceThingRepositoryMock(mc)
 
 				mock.DeleteThingMock.Inspect(func(ctx context.Context, id int, tx *sql.Tx) {
 					assert.Equal(mc, thingID, id)
@@ -278,8 +278,8 @@ func Test_DeleteThingHandler(t *testing.T) {
 
 				return mock
 			},
-			thingImageRepoMock: func(mc *minimock.Controller) interfaces.ThingImageRepository {
-				mock := repoMocks.NewThingImageRepositoryMock(mc)
+			thingImageRepoMock: func(mc *minimock.Controller) ThingImageRepository {
+				mock := mocks.NewThingImageRepositoryMock(mc)
 
 				mock.GetByThingIDMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -291,22 +291,22 @@ func Test_DeleteThingHandler(t *testing.T) {
 
 				return mock
 			},
-			thingTagRepoMock: func(mc *minimock.Controller) interfaces.ThingTagRepository {
-				return repoMocks.NewThingTagRepositoryMock(mc)
+			thingTagRepoMock: func(mc *minimock.Controller) ThingTagRepository {
+				return mocks.NewThingTagRepositoryMock(mc)
 			},
-			thingNotificationRepoMock: func(mc *minimock.Controller) interfaces.ThingNotificationRepository {
-				return repoMocks.NewThingNotificationRepositoryMock(mc)
+			thingNotificationRepoMock: func(mc *minimock.Controller) ThingNotificationRepository {
+				return mocks.NewThingNotificationRepositoryMock(mc)
 			},
-			fileRepoMock: func(mc *minimock.Controller) interfaces.FileRepository {
-				return repoMocks.NewFileRepositoryMock(mc)
+			fileRepoMock: func(mc *minimock.Controller) FileRepository {
+				return mocks.NewFileRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - repository error (delete thing tags)",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				mock := repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				mock := mocks.NewThingRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -316,8 +316,8 @@ func Test_DeleteThingHandler(t *testing.T) {
 
 				return mock
 			},
-			placeThingRepoMock: func(mc *minimock.Controller) interfaces.PlaceThingRepository {
-				mock := repoMocks.NewPlaceThingRepositoryMock(mc)
+			placeThingRepoMock: func(mc *minimock.Controller) PlaceThingRepository {
+				mock := mocks.NewPlaceThingRepositoryMock(mc)
 
 				mock.DeleteThingMock.Inspect(func(ctx context.Context, id int, tx *sql.Tx) {
 					assert.Equal(mc, thingID, id)
@@ -325,8 +325,8 @@ func Test_DeleteThingHandler(t *testing.T) {
 
 				return mock
 			},
-			thingImageRepoMock: func(mc *minimock.Controller) interfaces.ThingImageRepository {
-				mock := repoMocks.NewThingImageRepositoryMock(mc)
+			thingImageRepoMock: func(mc *minimock.Controller) ThingImageRepository {
+				mock := mocks.NewThingImageRepositoryMock(mc)
 
 				mock.GetByThingIDMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -338,8 +338,8 @@ func Test_DeleteThingHandler(t *testing.T) {
 
 				return mock
 			},
-			thingTagRepoMock: func(mc *minimock.Controller) interfaces.ThingTagRepository {
-				mock := repoMocks.NewThingTagRepositoryMock(mc)
+			thingTagRepoMock: func(mc *minimock.Controller) ThingTagRepository {
+				mock := mocks.NewThingTagRepositoryMock(mc)
 
 				mock.DeleteByThingIDMock.Inspect(func(ctx context.Context, id int, tx *sql.Tx) {
 					assert.Equal(mc, thingID, id)
@@ -347,19 +347,19 @@ func Test_DeleteThingHandler(t *testing.T) {
 
 				return mock
 			},
-			thingNotificationRepoMock: func(mc *minimock.Controller) interfaces.ThingNotificationRepository {
-				return repoMocks.NewThingNotificationRepositoryMock(mc)
+			thingNotificationRepoMock: func(mc *minimock.Controller) ThingNotificationRepository {
+				return mocks.NewThingNotificationRepositoryMock(mc)
 			},
-			fileRepoMock: func(mc *minimock.Controller) interfaces.FileRepository {
-				return repoMocks.NewFileRepositoryMock(mc)
+			fileRepoMock: func(mc *minimock.Controller) FileRepository {
+				return mocks.NewFileRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - repository error (delete notification)",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				mock := repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				mock := mocks.NewThingRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -369,8 +369,8 @@ func Test_DeleteThingHandler(t *testing.T) {
 
 				return mock
 			},
-			placeThingRepoMock: func(mc *minimock.Controller) interfaces.PlaceThingRepository {
-				mock := repoMocks.NewPlaceThingRepositoryMock(mc)
+			placeThingRepoMock: func(mc *minimock.Controller) PlaceThingRepository {
+				mock := mocks.NewPlaceThingRepositoryMock(mc)
 
 				mock.DeleteThingMock.Inspect(func(ctx context.Context, id int, tx *sql.Tx) {
 					assert.Equal(mc, thingID, id)
@@ -378,8 +378,8 @@ func Test_DeleteThingHandler(t *testing.T) {
 
 				return mock
 			},
-			thingImageRepoMock: func(mc *minimock.Controller) interfaces.ThingImageRepository {
-				mock := repoMocks.NewThingImageRepositoryMock(mc)
+			thingImageRepoMock: func(mc *minimock.Controller) ThingImageRepository {
+				mock := mocks.NewThingImageRepositoryMock(mc)
 
 				mock.GetByThingIDMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -391,8 +391,8 @@ func Test_DeleteThingHandler(t *testing.T) {
 
 				return mock
 			},
-			thingTagRepoMock: func(mc *minimock.Controller) interfaces.ThingTagRepository {
-				mock := repoMocks.NewThingTagRepositoryMock(mc)
+			thingTagRepoMock: func(mc *minimock.Controller) ThingTagRepository {
+				mock := mocks.NewThingTagRepositoryMock(mc)
 
 				mock.DeleteByThingIDMock.Inspect(func(ctx context.Context, id int, tx *sql.Tx) {
 					assert.Equal(mc, thingID, id)
@@ -400,8 +400,8 @@ func Test_DeleteThingHandler(t *testing.T) {
 
 				return mock
 			},
-			thingNotificationRepoMock: func(mc *minimock.Controller) interfaces.ThingNotificationRepository {
-				mock := repoMocks.NewThingNotificationRepositoryMock(mc)
+			thingNotificationRepoMock: func(mc *minimock.Controller) ThingNotificationRepository {
+				mock := mocks.NewThingNotificationRepositoryMock(mc)
 
 				mock.DeleteMock.Inspect(func(ctx context.Context, id int, tx *sql.Tx) {
 					assert.Equal(mc, thingID, id)
@@ -409,16 +409,16 @@ func Test_DeleteThingHandler(t *testing.T) {
 
 				return mock
 			},
-			fileRepoMock: func(mc *minimock.Controller) interfaces.FileRepository {
-				return repoMocks.NewFileRepositoryMock(mc)
+			fileRepoMock: func(mc *minimock.Controller) FileRepository {
+				return mocks.NewFileRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - repository error (delete thing)",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				mock := repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				mock := mocks.NewThingRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -432,8 +432,8 @@ func Test_DeleteThingHandler(t *testing.T) {
 
 				return mock
 			},
-			placeThingRepoMock: func(mc *minimock.Controller) interfaces.PlaceThingRepository {
-				mock := repoMocks.NewPlaceThingRepositoryMock(mc)
+			placeThingRepoMock: func(mc *minimock.Controller) PlaceThingRepository {
+				mock := mocks.NewPlaceThingRepositoryMock(mc)
 
 				mock.DeleteThingMock.Inspect(func(ctx context.Context, id int, tx *sql.Tx) {
 					assert.Equal(mc, thingID, id)
@@ -441,8 +441,8 @@ func Test_DeleteThingHandler(t *testing.T) {
 
 				return mock
 			},
-			thingImageRepoMock: func(mc *minimock.Controller) interfaces.ThingImageRepository {
-				mock := repoMocks.NewThingImageRepositoryMock(mc)
+			thingImageRepoMock: func(mc *minimock.Controller) ThingImageRepository {
+				mock := mocks.NewThingImageRepositoryMock(mc)
 
 				mock.GetByThingIDMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -454,8 +454,8 @@ func Test_DeleteThingHandler(t *testing.T) {
 
 				return mock
 			},
-			thingTagRepoMock: func(mc *minimock.Controller) interfaces.ThingTagRepository {
-				mock := repoMocks.NewThingTagRepositoryMock(mc)
+			thingTagRepoMock: func(mc *minimock.Controller) ThingTagRepository {
+				mock := mocks.NewThingTagRepositoryMock(mc)
 
 				mock.DeleteByThingIDMock.Inspect(func(ctx context.Context, id int, tx *sql.Tx) {
 					assert.Equal(mc, thingID, id)
@@ -463,8 +463,8 @@ func Test_DeleteThingHandler(t *testing.T) {
 
 				return mock
 			},
-			thingNotificationRepoMock: func(mc *minimock.Controller) interfaces.ThingNotificationRepository {
-				mock := repoMocks.NewThingNotificationRepositoryMock(mc)
+			thingNotificationRepoMock: func(mc *minimock.Controller) ThingNotificationRepository {
+				mock := mocks.NewThingNotificationRepositoryMock(mc)
 
 				mock.DeleteMock.Inspect(func(ctx context.Context, id int, tx *sql.Tx) {
 					assert.Equal(mc, thingID, id)
@@ -472,16 +472,16 @@ func Test_DeleteThingHandler(t *testing.T) {
 
 				return mock
 			},
-			fileRepoMock: func(mc *minimock.Controller) interfaces.FileRepository {
-				return repoMocks.NewFileRepositoryMock(mc)
+			fileRepoMock: func(mc *minimock.Controller) FileRepository {
+				return mocks.NewFileRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - repository error (commit tx)",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				mock := repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				mock := mocks.NewThingRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -497,8 +497,8 @@ func Test_DeleteThingHandler(t *testing.T) {
 
 				return mock
 			},
-			placeThingRepoMock: func(mc *minimock.Controller) interfaces.PlaceThingRepository {
-				mock := repoMocks.NewPlaceThingRepositoryMock(mc)
+			placeThingRepoMock: func(mc *minimock.Controller) PlaceThingRepository {
+				mock := mocks.NewPlaceThingRepositoryMock(mc)
 
 				mock.DeleteThingMock.Inspect(func(ctx context.Context, id int, tx *sql.Tx) {
 					assert.Equal(mc, thingID, id)
@@ -506,8 +506,8 @@ func Test_DeleteThingHandler(t *testing.T) {
 
 				return mock
 			},
-			thingImageRepoMock: func(mc *minimock.Controller) interfaces.ThingImageRepository {
-				mock := repoMocks.NewThingImageRepositoryMock(mc)
+			thingImageRepoMock: func(mc *minimock.Controller) ThingImageRepository {
+				mock := mocks.NewThingImageRepositoryMock(mc)
 
 				mock.GetByThingIDMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -519,8 +519,8 @@ func Test_DeleteThingHandler(t *testing.T) {
 
 				return mock
 			},
-			thingTagRepoMock: func(mc *minimock.Controller) interfaces.ThingTagRepository {
-				mock := repoMocks.NewThingTagRepositoryMock(mc)
+			thingTagRepoMock: func(mc *minimock.Controller) ThingTagRepository {
+				mock := mocks.NewThingTagRepositoryMock(mc)
 
 				mock.DeleteByThingIDMock.Inspect(func(ctx context.Context, id int, tx *sql.Tx) {
 					assert.Equal(mc, thingID, id)
@@ -528,8 +528,8 @@ func Test_DeleteThingHandler(t *testing.T) {
 
 				return mock
 			},
-			thingNotificationRepoMock: func(mc *minimock.Controller) interfaces.ThingNotificationRepository {
-				mock := repoMocks.NewThingNotificationRepositoryMock(mc)
+			thingNotificationRepoMock: func(mc *minimock.Controller) ThingNotificationRepository {
+				mock := mocks.NewThingNotificationRepositoryMock(mc)
 
 				mock.DeleteMock.Inspect(func(ctx context.Context, id int, tx *sql.Tx) {
 					assert.Equal(mc, thingID, id)
@@ -537,16 +537,16 @@ func Test_DeleteThingHandler(t *testing.T) {
 
 				return mock
 			},
-			fileRepoMock: func(mc *minimock.Controller) interfaces.FileRepository {
-				return repoMocks.NewFileRepositoryMock(mc)
+			fileRepoMock: func(mc *minimock.Controller) FileRepository {
+				return mocks.NewFileRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - file delete error",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				mock := repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				mock := mocks.NewThingRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -562,8 +562,8 @@ func Test_DeleteThingHandler(t *testing.T) {
 
 				return mock
 			},
-			placeThingRepoMock: func(mc *minimock.Controller) interfaces.PlaceThingRepository {
-				mock := repoMocks.NewPlaceThingRepositoryMock(mc)
+			placeThingRepoMock: func(mc *minimock.Controller) PlaceThingRepository {
+				mock := mocks.NewPlaceThingRepositoryMock(mc)
 
 				mock.DeleteThingMock.Inspect(func(ctx context.Context, id int, tx *sql.Tx) {
 					assert.Equal(mc, thingID, id)
@@ -571,8 +571,8 @@ func Test_DeleteThingHandler(t *testing.T) {
 
 				return mock
 			},
-			thingImageRepoMock: func(mc *minimock.Controller) interfaces.ThingImageRepository {
-				mock := repoMocks.NewThingImageRepositoryMock(mc)
+			thingImageRepoMock: func(mc *minimock.Controller) ThingImageRepository {
+				mock := mocks.NewThingImageRepositoryMock(mc)
 
 				mock.GetByThingIDMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -584,8 +584,8 @@ func Test_DeleteThingHandler(t *testing.T) {
 
 				return mock
 			},
-			thingTagRepoMock: func(mc *minimock.Controller) interfaces.ThingTagRepository {
-				mock := repoMocks.NewThingTagRepositoryMock(mc)
+			thingTagRepoMock: func(mc *minimock.Controller) ThingTagRepository {
+				mock := mocks.NewThingTagRepositoryMock(mc)
 
 				mock.DeleteByThingIDMock.Inspect(func(ctx context.Context, id int, tx *sql.Tx) {
 					assert.Equal(mc, thingID, id)
@@ -593,8 +593,8 @@ func Test_DeleteThingHandler(t *testing.T) {
 
 				return mock
 			},
-			thingNotificationRepoMock: func(mc *minimock.Controller) interfaces.ThingNotificationRepository {
-				mock := repoMocks.NewThingNotificationRepositoryMock(mc)
+			thingNotificationRepoMock: func(mc *minimock.Controller) ThingNotificationRepository {
+				mock := mocks.NewThingNotificationRepositoryMock(mc)
 
 				mock.DeleteMock.Inspect(func(ctx context.Context, id int, tx *sql.Tx) {
 					assert.Equal(mc, thingID, id)
@@ -602,8 +602,8 @@ func Test_DeleteThingHandler(t *testing.T) {
 
 				return mock
 			},
-			fileRepoMock: func(mc *minimock.Controller) interfaces.FileRepository {
-				mock := repoMocks.NewFileRepositoryMock(mc)
+			fileRepoMock: func(mc *minimock.Controller) FileRepository {
+				mock := mocks.NewFileRepositoryMock(mc)
 				mock.DeleteMock.Return(testError)
 				return mock
 			},
@@ -613,8 +613,8 @@ func Test_DeleteThingHandler(t *testing.T) {
 			req:     correctReq,
 			resCode: fiber.StatusOK,
 			resBody: dto.EmptyResponse{},
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				mock := repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				mock := mocks.NewThingRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -630,8 +630,8 @@ func Test_DeleteThingHandler(t *testing.T) {
 
 				return mock
 			},
-			placeThingRepoMock: func(mc *minimock.Controller) interfaces.PlaceThingRepository {
-				mock := repoMocks.NewPlaceThingRepositoryMock(mc)
+			placeThingRepoMock: func(mc *minimock.Controller) PlaceThingRepository {
+				mock := mocks.NewPlaceThingRepositoryMock(mc)
 
 				mock.DeleteThingMock.Inspect(func(ctx context.Context, id int, tx *sql.Tx) {
 					assert.Equal(mc, thingID, id)
@@ -639,8 +639,8 @@ func Test_DeleteThingHandler(t *testing.T) {
 
 				return mock
 			},
-			thingImageRepoMock: func(mc *minimock.Controller) interfaces.ThingImageRepository {
-				mock := repoMocks.NewThingImageRepositoryMock(mc)
+			thingImageRepoMock: func(mc *minimock.Controller) ThingImageRepository {
+				mock := mocks.NewThingImageRepositoryMock(mc)
 
 				mock.GetByThingIDMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -652,8 +652,8 @@ func Test_DeleteThingHandler(t *testing.T) {
 
 				return mock
 			},
-			thingTagRepoMock: func(mc *minimock.Controller) interfaces.ThingTagRepository {
-				mock := repoMocks.NewThingTagRepositoryMock(mc)
+			thingTagRepoMock: func(mc *minimock.Controller) ThingTagRepository {
+				mock := mocks.NewThingTagRepositoryMock(mc)
 
 				mock.DeleteByThingIDMock.Inspect(func(ctx context.Context, id int, tx *sql.Tx) {
 					assert.Equal(mc, thingID, id)
@@ -661,8 +661,8 @@ func Test_DeleteThingHandler(t *testing.T) {
 
 				return mock
 			},
-			thingNotificationRepoMock: func(mc *minimock.Controller) interfaces.ThingNotificationRepository {
-				mock := repoMocks.NewThingNotificationRepositoryMock(mc)
+			thingNotificationRepoMock: func(mc *minimock.Controller) ThingNotificationRepository {
+				mock := mocks.NewThingNotificationRepositoryMock(mc)
 
 				mock.DeleteMock.Inspect(func(ctx context.Context, id int, tx *sql.Tx) {
 					assert.Equal(mc, thingID, id)
@@ -670,8 +670,8 @@ func Test_DeleteThingHandler(t *testing.T) {
 
 				return mock
 			},
-			fileRepoMock: func(mc *minimock.Controller) interfaces.FileRepository {
-				mock := repoMocks.NewFileRepositoryMock(mc)
+			fileRepoMock: func(mc *minimock.Controller) FileRepository {
+				mock := mocks.NewFileRepositoryMock(mc)
 				mock.DeleteMock.Return(nil)
 				return mock
 			},
@@ -680,17 +680,19 @@ func Test_DeleteThingHandler(t *testing.T) {
 
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
+			t.Parallel()
+
+			mc := minimock.NewController(t)
 			fiberApp := fiber.New()
-			serviceProvider := sp.InitMock(
+
+			fiberApp.Delete("/v1/things/:thingId", DeleteThingHandler(
 				tt.thingRepoMock(mc),
+				tt.thingTagRepoMock(mc),
 				tt.placeThingRepoMock(mc),
 				tt.thingImageRepoMock(mc),
-				tt.thingTagRepoMock(mc),
 				tt.thingNotificationRepoMock(mc),
 				tt.fileRepoMock(mc),
-			)
-
-			fiberApp.Delete("/v1/things/:thingId", DeleteThingHandler(serviceProvider))
+			))
 
 			fiberRes, _ := fiberApp.Test(httptest.NewRequest(tt.req.method, tt.req.route, nil), API.DefaultTestTimeOut)
 			assert.Equal(t, tt.resCode, fiberRes.StatusCode)

+ 9 - 6
internal/api/v1/thing/get_place_things.go

@@ -1,10 +1,10 @@
 package thing
 
 import (
+	"github.com/gofiber/fiber/v2"
+
 	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/mappers"
-	"github.com/gofiber/fiber/v2"
 )
 
 // @Router 		/api/v1/things/place/{placeId} [get]
@@ -17,7 +17,10 @@ import (
 // @security 	APIKey
 // @Accept      json
 // @Produce     json
-func GetPlaceThingsHandler(sp interfaces.ServiceProvider) fiber.Handler {
+func GetPlaceThingsHandler(
+	thingRepository ThingRepository,
+	thingTagRepository ThingTagRepository,
+) fiber.Handler {
 	return func(fctx *fiber.Ctx) error {
 		ctx := fctx.Context()
 		id, err := fctx.ParamsInt("placeId")
@@ -25,12 +28,12 @@ func GetPlaceThingsHandler(sp interfaces.ServiceProvider) fiber.Handler {
 			return fiber.NewError(fiber.StatusBadRequest, err.Error())
 		}
 
-		things, err := sp.GetThingRepository().GetAllByPlaceID(ctx, id)
+		things, err := thingRepository.GetAllByPlaceID(ctx, id)
 		if err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
-		tags, err := sp.GetThingTagRepository().GetByPlaceID(ctx, id)
+		tags, err := thingTagRepository.GetByPlaceID(ctx, id)
 		if err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
@@ -38,6 +41,6 @@ func GetPlaceThingsHandler(sp interfaces.ServiceProvider) fiber.Handler {
 		things = helpers.ApplyLocation(fctx, things)
 		tags = helpers.ApplyLocation(fctx, tags)
 
-		return fctx.JSON(mappers.ConvertToThingsExtResponseDTO(things, tags))
+		return fctx.JSON(mappers.ToThingsExtResponse(things, tags))
 	}
 }

+ 31 - 30
internal/api/v1/thing/get_place_things_test.go

@@ -7,27 +7,27 @@ import (
 	"strconv"
 	"testing"
 
-	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
-	repoMocks "git.dmitriygnatenko.ru/dima/homethings/internal/repositories/mocks"
-	sp "git.dmitriygnatenko.ru/dima/homethings/internal/service_provider"
 	"github.com/brianvoe/gofakeit/v6"
 	"github.com/gofiber/fiber/v2"
 	"github.com/gojuno/minimock/v3"
 	"github.com/stretchr/testify/assert"
+
+	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/thing/mocks"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
 )
 
-func Test_GetPlaceThingsHandler(t *testing.T) {
+func TestGetPlaceThingsHandler(t *testing.T) {
+	t.Parallel()
+
 	type req struct {
 		method string
 		route  string
 	}
 
 	var (
-		mc        = minimock.NewController(t)
 		placeID   = gofakeit.Number(1, 1000)
 		testError = errors.New(gofakeit.Phrase())
 		layout    = "2006-01-02 15:04:05"
@@ -128,16 +128,16 @@ func Test_GetPlaceThingsHandler(t *testing.T) {
 		req              req
 		resCode          int
 		resBody          interface{}
-		thingRepoMock    func(mc *minimock.Controller) interfaces.ThingRepository
-		thingTagRepoMock func(mc *minimock.Controller) interfaces.ThingTagRepository
+		thingRepoMock    func(mc *minimock.Controller) ThingRepository
+		thingTagRepoMock func(mc *minimock.Controller) ThingTagRepository
 	}{
 		{
 			name:    "positive case",
 			req:     correctReq,
 			resCode: fiber.StatusOK,
 			resBody: expectedRes,
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				mock := repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				mock := mocks.NewThingRepositoryMock(mc)
 
 				mock.GetAllByPlaceIDMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, placeID, id)
@@ -145,8 +145,8 @@ func Test_GetPlaceThingsHandler(t *testing.T) {
 
 				return mock
 			},
-			thingTagRepoMock: func(mc *minimock.Controller) interfaces.ThingTagRepository {
-				mock := repoMocks.NewThingTagRepositoryMock(mc)
+			thingTagRepoMock: func(mc *minimock.Controller) ThingTagRepository {
+				mock := mocks.NewThingTagRepositoryMock(mc)
 
 				mock.GetByPlaceIDMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, placeID, id)
@@ -159,8 +159,8 @@ func Test_GetPlaceThingsHandler(t *testing.T) {
 			name:    "negative case - thing repository error",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				mock := repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				mock := mocks.NewThingRepositoryMock(mc)
 
 				mock.GetAllByPlaceIDMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, placeID, id)
@@ -168,16 +168,16 @@ func Test_GetPlaceThingsHandler(t *testing.T) {
 
 				return mock
 			},
-			thingTagRepoMock: func(mc *minimock.Controller) interfaces.ThingTagRepository {
-				return repoMocks.NewThingTagRepositoryMock(mc)
+			thingTagRepoMock: func(mc *minimock.Controller) ThingTagRepository {
+				return mocks.NewThingTagRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - thing tag repository error",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				mock := repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				mock := mocks.NewThingRepositoryMock(mc)
 
 				mock.GetAllByPlaceIDMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, placeID, id)
@@ -185,8 +185,8 @@ func Test_GetPlaceThingsHandler(t *testing.T) {
 
 				return mock
 			},
-			thingTagRepoMock: func(mc *minimock.Controller) interfaces.ThingTagRepository {
-				mock := repoMocks.NewThingTagRepositoryMock(mc)
+			thingTagRepoMock: func(mc *minimock.Controller) ThingTagRepository {
+				mock := mocks.NewThingTagRepositoryMock(mc)
 
 				mock.GetByPlaceIDMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, placeID, id)
@@ -203,21 +203,22 @@ func Test_GetPlaceThingsHandler(t *testing.T) {
 			},
 			resCode: fiber.StatusBadRequest,
 			resBody: nil,
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				return repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				return mocks.NewThingRepositoryMock(mc)
 			},
-			thingTagRepoMock: func(mc *minimock.Controller) interfaces.ThingTagRepository {
-				return repoMocks.NewThingTagRepositoryMock(mc)
+			thingTagRepoMock: func(mc *minimock.Controller) ThingTagRepository {
+				return mocks.NewThingTagRepositoryMock(mc)
 			},
 		},
 	}
 
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			fiberApp := fiber.New()
-			serviceProvider := sp.InitMock(tt.thingRepoMock(mc), tt.thingTagRepoMock(mc))
+			t.Parallel()
 
-			fiberApp.Get("/v1/things/place/:placeId", GetPlaceThingsHandler(serviceProvider))
+			mc := minimock.NewController(t)
+			fiberApp := fiber.New()
+			fiberApp.Get("/v1/things/place/:placeId", GetPlaceThingsHandler(tt.thingRepoMock(mc), tt.thingTagRepoMock(mc)))
 
 			fiberRes, _ := fiberApp.Test(httptest.NewRequest(tt.req.method, tt.req.route, nil), API.DefaultTestTimeOut)
 			assert.Equal(t, tt.resCode, fiberRes.StatusCode)

+ 7 - 6
internal/api/v1/thing/get_thing.go

@@ -2,11 +2,12 @@ package thing
 
 import (
 	"database/sql"
+	"errors"
+
+	"github.com/gofiber/fiber/v2"
 
 	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/mappers"
-	"github.com/gofiber/fiber/v2"
 )
 
 // @Router 		/api/v1/things/{thingId} [get]
@@ -20,7 +21,7 @@ import (
 // @security 	APIKey
 // @Accept      json
 // @Produce     json
-func GetThingHandler(sp interfaces.ServiceProvider) fiber.Handler {
+func GetThingHandler(thingRepository ThingRepository) fiber.Handler {
 	return func(fctx *fiber.Ctx) error {
 		ctx := fctx.Context()
 		id, err := fctx.ParamsInt("thingId")
@@ -28,9 +29,9 @@ func GetThingHandler(sp interfaces.ServiceProvider) fiber.Handler {
 			return fiber.NewError(fiber.StatusBadRequest, err.Error())
 		}
 
-		res, err := sp.GetThingRepository().Get(ctx, id)
+		res, err := thingRepository.Get(ctx, id)
 		if err != nil {
-			if err == sql.ErrNoRows {
+			if errors.Is(err, sql.ErrNoRows) {
 				return fiber.NewError(fiber.StatusNotFound, "")
 			}
 
@@ -39,6 +40,6 @@ func GetThingHandler(sp interfaces.ServiceProvider) fiber.Handler {
 
 		res = helpers.ApplyLocation(fctx, res)
 
-		return fctx.JSON(mappers.ConvertToThingResponseDTO(*res))
+		return fctx.JSON(mappers.ToThingResponse(*res))
 	}
 }

+ 22 - 21
internal/api/v1/thing/get_thing_test.go

@@ -8,27 +8,27 @@ import (
 	"strconv"
 	"testing"
 
-	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
-	repoMocks "git.dmitriygnatenko.ru/dima/homethings/internal/repositories/mocks"
-	sp "git.dmitriygnatenko.ru/dima/homethings/internal/service_provider"
 	"github.com/brianvoe/gofakeit/v6"
 	"github.com/gofiber/fiber/v2"
 	"github.com/gojuno/minimock/v3"
 	"github.com/stretchr/testify/assert"
+
+	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/thing/mocks"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
 )
 
-func Test_GetThingHandler(t *testing.T) {
+func TestGetThingHandler(t *testing.T) {
+	t.Parallel()
+
 	type req struct {
 		method string
 		route  string
 	}
 
 	var (
-		mc        = minimock.NewController(t)
 		thingID   = gofakeit.Number(1, 1000)
 		placeID   = gofakeit.Number(1, 1000)
 		testError = errors.New(gofakeit.Phrase())
@@ -63,15 +63,15 @@ func Test_GetThingHandler(t *testing.T) {
 		req           req
 		resCode       int
 		resBody       interface{}
-		thingRepoMock func(mc *minimock.Controller) interfaces.ThingRepository
+		thingRepoMock func(mc *minimock.Controller) ThingRepository
 	}{
 		{
 			name:    "positive case",
 			req:     correctReq,
 			resCode: fiber.StatusOK,
 			resBody: expectedRes,
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				mock := repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				mock := mocks.NewThingRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -84,8 +84,8 @@ func Test_GetThingHandler(t *testing.T) {
 			name:    "negative case - not found",
 			req:     correctReq,
 			resCode: fiber.StatusNotFound,
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				mock := repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				mock := mocks.NewThingRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -98,8 +98,8 @@ func Test_GetThingHandler(t *testing.T) {
 			name:    "negative case - repository error",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				mock := repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				mock := mocks.NewThingRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -116,18 +116,19 @@ func Test_GetThingHandler(t *testing.T) {
 			},
 			resCode: fiber.StatusBadRequest,
 			resBody: nil,
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				return repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				return mocks.NewThingRepositoryMock(mc)
 			},
 		},
 	}
 
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			fiberApp := fiber.New()
-			serviceProvider := sp.InitMock(tt.thingRepoMock(mc))
+			t.Parallel()
 
-			fiberApp.Get("/v1/things/:thingId", GetThingHandler(serviceProvider))
+			mc := minimock.NewController(t)
+			fiberApp := fiber.New()
+			fiberApp.Get("/v1/things/:thingId", GetThingHandler(tt.thingRepoMock(mc)))
 
 			fiberRes, _ := fiberApp.Test(httptest.NewRequest(tt.req.method, tt.req.route, nil), API.DefaultTestTimeOut)
 			assert.Equal(t, tt.resCode, fiberRes.StatusCode)

+ 364 - 0
internal/api/v1/thing/mocks/file_repository_minimock.go

@@ -0,0 +1,364 @@
+// Code generated by http://github.com/gojuno/minimock (v3.3.13). DO NOT EDIT.
+
+package mocks
+
+//go:generate minimock -i git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/thing.FileRepository -o file_repository_minimock.go -n FileRepositoryMock -p mocks
+
+import (
+	"sync"
+	mm_atomic "sync/atomic"
+	mm_time "time"
+
+	"github.com/gojuno/minimock/v3"
+)
+
+// FileRepositoryMock implements thing.FileRepository
+type FileRepositoryMock struct {
+	t          minimock.Tester
+	finishOnce sync.Once
+
+	funcDelete          func(path string) (err error)
+	inspectFuncDelete   func(path string)
+	afterDeleteCounter  uint64
+	beforeDeleteCounter uint64
+	DeleteMock          mFileRepositoryMockDelete
+}
+
+// NewFileRepositoryMock returns a mock for thing.FileRepository
+func NewFileRepositoryMock(t minimock.Tester) *FileRepositoryMock {
+	m := &FileRepositoryMock{t: t}
+
+	if controller, ok := t.(minimock.MockController); ok {
+		controller.RegisterMocker(m)
+	}
+
+	m.DeleteMock = mFileRepositoryMockDelete{mock: m}
+	m.DeleteMock.callArgs = []*FileRepositoryMockDeleteParams{}
+
+	t.Cleanup(m.MinimockFinish)
+
+	return m
+}
+
+type mFileRepositoryMockDelete struct {
+	optional           bool
+	mock               *FileRepositoryMock
+	defaultExpectation *FileRepositoryMockDeleteExpectation
+	expectations       []*FileRepositoryMockDeleteExpectation
+
+	callArgs []*FileRepositoryMockDeleteParams
+	mutex    sync.RWMutex
+
+	expectedInvocations uint64
+}
+
+// FileRepositoryMockDeleteExpectation specifies expectation struct of the FileRepository.Delete
+type FileRepositoryMockDeleteExpectation struct {
+	mock      *FileRepositoryMock
+	params    *FileRepositoryMockDeleteParams
+	paramPtrs *FileRepositoryMockDeleteParamPtrs
+	results   *FileRepositoryMockDeleteResults
+	Counter   uint64
+}
+
+// FileRepositoryMockDeleteParams contains parameters of the FileRepository.Delete
+type FileRepositoryMockDeleteParams struct {
+	path string
+}
+
+// FileRepositoryMockDeleteParamPtrs contains pointers to parameters of the FileRepository.Delete
+type FileRepositoryMockDeleteParamPtrs struct {
+	path *string
+}
+
+// FileRepositoryMockDeleteResults contains results of the FileRepository.Delete
+type FileRepositoryMockDeleteResults struct {
+	err error
+}
+
+// Marks this method to be optional. The default behavior of any method with Return() is '1 or more', meaning
+// the test will fail minimock's automatic final call check if the mocked method was not called at least once.
+// Optional() makes method check to work in '0 or more' mode.
+// It is NOT RECOMMENDED to use this option unless you really need it, as default behaviour helps to
+// catch the problems when the expected method call is totally skipped during test run.
+func (mmDelete *mFileRepositoryMockDelete) Optional() *mFileRepositoryMockDelete {
+	mmDelete.optional = true
+	return mmDelete
+}
+
+// Expect sets up expected params for FileRepository.Delete
+func (mmDelete *mFileRepositoryMockDelete) Expect(path string) *mFileRepositoryMockDelete {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("FileRepositoryMock.Delete mock is already set by Set")
+	}
+
+	if mmDelete.defaultExpectation == nil {
+		mmDelete.defaultExpectation = &FileRepositoryMockDeleteExpectation{}
+	}
+
+	if mmDelete.defaultExpectation.paramPtrs != nil {
+		mmDelete.mock.t.Fatalf("FileRepositoryMock.Delete mock is already set by ExpectParams functions")
+	}
+
+	mmDelete.defaultExpectation.params = &FileRepositoryMockDeleteParams{path}
+	for _, e := range mmDelete.expectations {
+		if minimock.Equal(e.params, mmDelete.defaultExpectation.params) {
+			mmDelete.mock.t.Fatalf("Expectation set by When has same params: %#v", *mmDelete.defaultExpectation.params)
+		}
+	}
+
+	return mmDelete
+}
+
+// ExpectPathParam1 sets up expected param path for FileRepository.Delete
+func (mmDelete *mFileRepositoryMockDelete) ExpectPathParam1(path string) *mFileRepositoryMockDelete {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("FileRepositoryMock.Delete mock is already set by Set")
+	}
+
+	if mmDelete.defaultExpectation == nil {
+		mmDelete.defaultExpectation = &FileRepositoryMockDeleteExpectation{}
+	}
+
+	if mmDelete.defaultExpectation.params != nil {
+		mmDelete.mock.t.Fatalf("FileRepositoryMock.Delete mock is already set by Expect")
+	}
+
+	if mmDelete.defaultExpectation.paramPtrs == nil {
+		mmDelete.defaultExpectation.paramPtrs = &FileRepositoryMockDeleteParamPtrs{}
+	}
+	mmDelete.defaultExpectation.paramPtrs.path = &path
+
+	return mmDelete
+}
+
+// Inspect accepts an inspector function that has same arguments as the FileRepository.Delete
+func (mmDelete *mFileRepositoryMockDelete) Inspect(f func(path string)) *mFileRepositoryMockDelete {
+	if mmDelete.mock.inspectFuncDelete != nil {
+		mmDelete.mock.t.Fatalf("Inspect function is already set for FileRepositoryMock.Delete")
+	}
+
+	mmDelete.mock.inspectFuncDelete = f
+
+	return mmDelete
+}
+
+// Return sets up results that will be returned by FileRepository.Delete
+func (mmDelete *mFileRepositoryMockDelete) Return(err error) *FileRepositoryMock {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("FileRepositoryMock.Delete mock is already set by Set")
+	}
+
+	if mmDelete.defaultExpectation == nil {
+		mmDelete.defaultExpectation = &FileRepositoryMockDeleteExpectation{mock: mmDelete.mock}
+	}
+	mmDelete.defaultExpectation.results = &FileRepositoryMockDeleteResults{err}
+	return mmDelete.mock
+}
+
+// Set uses given function f to mock the FileRepository.Delete method
+func (mmDelete *mFileRepositoryMockDelete) Set(f func(path string) (err error)) *FileRepositoryMock {
+	if mmDelete.defaultExpectation != nil {
+		mmDelete.mock.t.Fatalf("Default expectation is already set for the FileRepository.Delete method")
+	}
+
+	if len(mmDelete.expectations) > 0 {
+		mmDelete.mock.t.Fatalf("Some expectations are already set for the FileRepository.Delete method")
+	}
+
+	mmDelete.mock.funcDelete = f
+	return mmDelete.mock
+}
+
+// When sets expectation for the FileRepository.Delete which will trigger the result defined by the following
+// Then helper
+func (mmDelete *mFileRepositoryMockDelete) When(path string) *FileRepositoryMockDeleteExpectation {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("FileRepositoryMock.Delete mock is already set by Set")
+	}
+
+	expectation := &FileRepositoryMockDeleteExpectation{
+		mock:   mmDelete.mock,
+		params: &FileRepositoryMockDeleteParams{path},
+	}
+	mmDelete.expectations = append(mmDelete.expectations, expectation)
+	return expectation
+}
+
+// Then sets up FileRepository.Delete return parameters for the expectation previously defined by the When method
+func (e *FileRepositoryMockDeleteExpectation) Then(err error) *FileRepositoryMock {
+	e.results = &FileRepositoryMockDeleteResults{err}
+	return e.mock
+}
+
+// Times sets number of times FileRepository.Delete should be invoked
+func (mmDelete *mFileRepositoryMockDelete) Times(n uint64) *mFileRepositoryMockDelete {
+	if n == 0 {
+		mmDelete.mock.t.Fatalf("Times of FileRepositoryMock.Delete mock can not be zero")
+	}
+	mm_atomic.StoreUint64(&mmDelete.expectedInvocations, n)
+	return mmDelete
+}
+
+func (mmDelete *mFileRepositoryMockDelete) invocationsDone() bool {
+	if len(mmDelete.expectations) == 0 && mmDelete.defaultExpectation == nil && mmDelete.mock.funcDelete == nil {
+		return true
+	}
+
+	totalInvocations := mm_atomic.LoadUint64(&mmDelete.mock.afterDeleteCounter)
+	expectedInvocations := mm_atomic.LoadUint64(&mmDelete.expectedInvocations)
+
+	return totalInvocations > 0 && (expectedInvocations == 0 || expectedInvocations == totalInvocations)
+}
+
+// Delete implements thing.FileRepository
+func (mmDelete *FileRepositoryMock) Delete(path string) (err error) {
+	mm_atomic.AddUint64(&mmDelete.beforeDeleteCounter, 1)
+	defer mm_atomic.AddUint64(&mmDelete.afterDeleteCounter, 1)
+
+	if mmDelete.inspectFuncDelete != nil {
+		mmDelete.inspectFuncDelete(path)
+	}
+
+	mm_params := FileRepositoryMockDeleteParams{path}
+
+	// Record call args
+	mmDelete.DeleteMock.mutex.Lock()
+	mmDelete.DeleteMock.callArgs = append(mmDelete.DeleteMock.callArgs, &mm_params)
+	mmDelete.DeleteMock.mutex.Unlock()
+
+	for _, e := range mmDelete.DeleteMock.expectations {
+		if minimock.Equal(*e.params, mm_params) {
+			mm_atomic.AddUint64(&e.Counter, 1)
+			return e.results.err
+		}
+	}
+
+	if mmDelete.DeleteMock.defaultExpectation != nil {
+		mm_atomic.AddUint64(&mmDelete.DeleteMock.defaultExpectation.Counter, 1)
+		mm_want := mmDelete.DeleteMock.defaultExpectation.params
+		mm_want_ptrs := mmDelete.DeleteMock.defaultExpectation.paramPtrs
+
+		mm_got := FileRepositoryMockDeleteParams{path}
+
+		if mm_want_ptrs != nil {
+
+			if mm_want_ptrs.path != nil && !minimock.Equal(*mm_want_ptrs.path, mm_got.path) {
+				mmDelete.t.Errorf("FileRepositoryMock.Delete got unexpected parameter path, want: %#v, got: %#v%s\n", *mm_want_ptrs.path, mm_got.path, minimock.Diff(*mm_want_ptrs.path, mm_got.path))
+			}
+
+		} else if mm_want != nil && !minimock.Equal(*mm_want, mm_got) {
+			mmDelete.t.Errorf("FileRepositoryMock.Delete got unexpected parameters, want: %#v, got: %#v%s\n", *mm_want, mm_got, minimock.Diff(*mm_want, mm_got))
+		}
+
+		mm_results := mmDelete.DeleteMock.defaultExpectation.results
+		if mm_results == nil {
+			mmDelete.t.Fatal("No results are set for the FileRepositoryMock.Delete")
+		}
+		return (*mm_results).err
+	}
+	if mmDelete.funcDelete != nil {
+		return mmDelete.funcDelete(path)
+	}
+	mmDelete.t.Fatalf("Unexpected call to FileRepositoryMock.Delete. %v", path)
+	return
+}
+
+// DeleteAfterCounter returns a count of finished FileRepositoryMock.Delete invocations
+func (mmDelete *FileRepositoryMock) DeleteAfterCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmDelete.afterDeleteCounter)
+}
+
+// DeleteBeforeCounter returns a count of FileRepositoryMock.Delete invocations
+func (mmDelete *FileRepositoryMock) DeleteBeforeCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmDelete.beforeDeleteCounter)
+}
+
+// Calls returns a list of arguments used in each call to FileRepositoryMock.Delete.
+// The list is in the same order as the calls were made (i.e. recent calls have a higher index)
+func (mmDelete *mFileRepositoryMockDelete) Calls() []*FileRepositoryMockDeleteParams {
+	mmDelete.mutex.RLock()
+
+	argCopy := make([]*FileRepositoryMockDeleteParams, len(mmDelete.callArgs))
+	copy(argCopy, mmDelete.callArgs)
+
+	mmDelete.mutex.RUnlock()
+
+	return argCopy
+}
+
+// MinimockDeleteDone returns true if the count of the Delete invocations corresponds
+// the number of defined expectations
+func (m *FileRepositoryMock) MinimockDeleteDone() bool {
+	if m.DeleteMock.optional {
+		// Optional methods provide '0 or more' call count restriction.
+		return true
+	}
+
+	for _, e := range m.DeleteMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			return false
+		}
+	}
+
+	return m.DeleteMock.invocationsDone()
+}
+
+// MinimockDeleteInspect logs each unmet expectation
+func (m *FileRepositoryMock) MinimockDeleteInspect() {
+	for _, e := range m.DeleteMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			m.t.Errorf("Expected call to FileRepositoryMock.Delete with params: %#v", *e.params)
+		}
+	}
+
+	afterDeleteCounter := mm_atomic.LoadUint64(&m.afterDeleteCounter)
+	// if default expectation was set then invocations count should be greater than zero
+	if m.DeleteMock.defaultExpectation != nil && afterDeleteCounter < 1 {
+		if m.DeleteMock.defaultExpectation.params == nil {
+			m.t.Error("Expected call to FileRepositoryMock.Delete")
+		} else {
+			m.t.Errorf("Expected call to FileRepositoryMock.Delete with params: %#v", *m.DeleteMock.defaultExpectation.params)
+		}
+	}
+	// if func was set then invocations count should be greater than zero
+	if m.funcDelete != nil && afterDeleteCounter < 1 {
+		m.t.Error("Expected call to FileRepositoryMock.Delete")
+	}
+
+	if !m.DeleteMock.invocationsDone() && afterDeleteCounter > 0 {
+		m.t.Errorf("Expected %d calls to FileRepositoryMock.Delete but found %d calls",
+			mm_atomic.LoadUint64(&m.DeleteMock.expectedInvocations), afterDeleteCounter)
+	}
+}
+
+// MinimockFinish checks that all mocked methods have been called the expected number of times
+func (m *FileRepositoryMock) MinimockFinish() {
+	m.finishOnce.Do(func() {
+		if !m.minimockDone() {
+			m.MinimockDeleteInspect()
+		}
+	})
+}
+
+// MinimockWait waits for all mocked methods to be called the expected number of times
+func (m *FileRepositoryMock) MinimockWait(timeout mm_time.Duration) {
+	timeoutCh := mm_time.After(timeout)
+	for {
+		if m.minimockDone() {
+			return
+		}
+		select {
+		case <-timeoutCh:
+			m.MinimockFinish()
+			return
+		case <-mm_time.After(10 * mm_time.Millisecond):
+		}
+	}
+}
+
+func (m *FileRepositoryMock) minimockDone() bool {
+	done := true
+	return done &&
+		m.MinimockDeleteDone()
+}

File diff ditekan karena terlalu besar
+ 555 - 74
internal/api/v1/thing/mocks/place_thing_repository_minimock.go


+ 756 - 0
internal/api/v1/thing/mocks/thing_image_repository_minimock.go

@@ -0,0 +1,756 @@
+// Code generated by http://github.com/gojuno/minimock (v3.3.13). DO NOT EDIT.
+
+package mocks
+
+//go:generate minimock -i git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/thing.ThingImageRepository -o thing_image_repository_minimock.go -n ThingImageRepositoryMock -p mocks
+
+import (
+	"context"
+	"database/sql"
+	"sync"
+	mm_atomic "sync/atomic"
+	mm_time "time"
+
+	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
+	"github.com/gojuno/minimock/v3"
+)
+
+// ThingImageRepositoryMock implements thing.ThingImageRepository
+type ThingImageRepositoryMock struct {
+	t          minimock.Tester
+	finishOnce sync.Once
+
+	funcDelete          func(ctx context.Context, imageID int, tx *sql.Tx) (err error)
+	inspectFuncDelete   func(ctx context.Context, imageID int, tx *sql.Tx)
+	afterDeleteCounter  uint64
+	beforeDeleteCounter uint64
+	DeleteMock          mThingImageRepositoryMockDelete
+
+	funcGetByThingID          func(ctx context.Context, thingID int) (ia1 []models.Image, err error)
+	inspectFuncGetByThingID   func(ctx context.Context, thingID int)
+	afterGetByThingIDCounter  uint64
+	beforeGetByThingIDCounter uint64
+	GetByThingIDMock          mThingImageRepositoryMockGetByThingID
+}
+
+// NewThingImageRepositoryMock returns a mock for thing.ThingImageRepository
+func NewThingImageRepositoryMock(t minimock.Tester) *ThingImageRepositoryMock {
+	m := &ThingImageRepositoryMock{t: t}
+
+	if controller, ok := t.(minimock.MockController); ok {
+		controller.RegisterMocker(m)
+	}
+
+	m.DeleteMock = mThingImageRepositoryMockDelete{mock: m}
+	m.DeleteMock.callArgs = []*ThingImageRepositoryMockDeleteParams{}
+
+	m.GetByThingIDMock = mThingImageRepositoryMockGetByThingID{mock: m}
+	m.GetByThingIDMock.callArgs = []*ThingImageRepositoryMockGetByThingIDParams{}
+
+	t.Cleanup(m.MinimockFinish)
+
+	return m
+}
+
+type mThingImageRepositoryMockDelete struct {
+	optional           bool
+	mock               *ThingImageRepositoryMock
+	defaultExpectation *ThingImageRepositoryMockDeleteExpectation
+	expectations       []*ThingImageRepositoryMockDeleteExpectation
+
+	callArgs []*ThingImageRepositoryMockDeleteParams
+	mutex    sync.RWMutex
+
+	expectedInvocations uint64
+}
+
+// ThingImageRepositoryMockDeleteExpectation specifies expectation struct of the ThingImageRepository.Delete
+type ThingImageRepositoryMockDeleteExpectation struct {
+	mock      *ThingImageRepositoryMock
+	params    *ThingImageRepositoryMockDeleteParams
+	paramPtrs *ThingImageRepositoryMockDeleteParamPtrs
+	results   *ThingImageRepositoryMockDeleteResults
+	Counter   uint64
+}
+
+// ThingImageRepositoryMockDeleteParams contains parameters of the ThingImageRepository.Delete
+type ThingImageRepositoryMockDeleteParams struct {
+	ctx     context.Context
+	imageID int
+	tx      *sql.Tx
+}
+
+// ThingImageRepositoryMockDeleteParamPtrs contains pointers to parameters of the ThingImageRepository.Delete
+type ThingImageRepositoryMockDeleteParamPtrs struct {
+	ctx     *context.Context
+	imageID *int
+	tx      **sql.Tx
+}
+
+// ThingImageRepositoryMockDeleteResults contains results of the ThingImageRepository.Delete
+type ThingImageRepositoryMockDeleteResults struct {
+	err error
+}
+
+// Marks this method to be optional. The default behavior of any method with Return() is '1 or more', meaning
+// the test will fail minimock's automatic final call check if the mocked method was not called at least once.
+// Optional() makes method check to work in '0 or more' mode.
+// It is NOT RECOMMENDED to use this option unless you really need it, as default behaviour helps to
+// catch the problems when the expected method call is totally skipped during test run.
+func (mmDelete *mThingImageRepositoryMockDelete) Optional() *mThingImageRepositoryMockDelete {
+	mmDelete.optional = true
+	return mmDelete
+}
+
+// Expect sets up expected params for ThingImageRepository.Delete
+func (mmDelete *mThingImageRepositoryMockDelete) Expect(ctx context.Context, imageID int, tx *sql.Tx) *mThingImageRepositoryMockDelete {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("ThingImageRepositoryMock.Delete mock is already set by Set")
+	}
+
+	if mmDelete.defaultExpectation == nil {
+		mmDelete.defaultExpectation = &ThingImageRepositoryMockDeleteExpectation{}
+	}
+
+	if mmDelete.defaultExpectation.paramPtrs != nil {
+		mmDelete.mock.t.Fatalf("ThingImageRepositoryMock.Delete mock is already set by ExpectParams functions")
+	}
+
+	mmDelete.defaultExpectation.params = &ThingImageRepositoryMockDeleteParams{ctx, imageID, tx}
+	for _, e := range mmDelete.expectations {
+		if minimock.Equal(e.params, mmDelete.defaultExpectation.params) {
+			mmDelete.mock.t.Fatalf("Expectation set by When has same params: %#v", *mmDelete.defaultExpectation.params)
+		}
+	}
+
+	return mmDelete
+}
+
+// ExpectCtxParam1 sets up expected param ctx for ThingImageRepository.Delete
+func (mmDelete *mThingImageRepositoryMockDelete) ExpectCtxParam1(ctx context.Context) *mThingImageRepositoryMockDelete {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("ThingImageRepositoryMock.Delete mock is already set by Set")
+	}
+
+	if mmDelete.defaultExpectation == nil {
+		mmDelete.defaultExpectation = &ThingImageRepositoryMockDeleteExpectation{}
+	}
+
+	if mmDelete.defaultExpectation.params != nil {
+		mmDelete.mock.t.Fatalf("ThingImageRepositoryMock.Delete mock is already set by Expect")
+	}
+
+	if mmDelete.defaultExpectation.paramPtrs == nil {
+		mmDelete.defaultExpectation.paramPtrs = &ThingImageRepositoryMockDeleteParamPtrs{}
+	}
+	mmDelete.defaultExpectation.paramPtrs.ctx = &ctx
+
+	return mmDelete
+}
+
+// ExpectImageIDParam2 sets up expected param imageID for ThingImageRepository.Delete
+func (mmDelete *mThingImageRepositoryMockDelete) ExpectImageIDParam2(imageID int) *mThingImageRepositoryMockDelete {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("ThingImageRepositoryMock.Delete mock is already set by Set")
+	}
+
+	if mmDelete.defaultExpectation == nil {
+		mmDelete.defaultExpectation = &ThingImageRepositoryMockDeleteExpectation{}
+	}
+
+	if mmDelete.defaultExpectation.params != nil {
+		mmDelete.mock.t.Fatalf("ThingImageRepositoryMock.Delete mock is already set by Expect")
+	}
+
+	if mmDelete.defaultExpectation.paramPtrs == nil {
+		mmDelete.defaultExpectation.paramPtrs = &ThingImageRepositoryMockDeleteParamPtrs{}
+	}
+	mmDelete.defaultExpectation.paramPtrs.imageID = &imageID
+
+	return mmDelete
+}
+
+// ExpectTxParam3 sets up expected param tx for ThingImageRepository.Delete
+func (mmDelete *mThingImageRepositoryMockDelete) ExpectTxParam3(tx *sql.Tx) *mThingImageRepositoryMockDelete {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("ThingImageRepositoryMock.Delete mock is already set by Set")
+	}
+
+	if mmDelete.defaultExpectation == nil {
+		mmDelete.defaultExpectation = &ThingImageRepositoryMockDeleteExpectation{}
+	}
+
+	if mmDelete.defaultExpectation.params != nil {
+		mmDelete.mock.t.Fatalf("ThingImageRepositoryMock.Delete mock is already set by Expect")
+	}
+
+	if mmDelete.defaultExpectation.paramPtrs == nil {
+		mmDelete.defaultExpectation.paramPtrs = &ThingImageRepositoryMockDeleteParamPtrs{}
+	}
+	mmDelete.defaultExpectation.paramPtrs.tx = &tx
+
+	return mmDelete
+}
+
+// Inspect accepts an inspector function that has same arguments as the ThingImageRepository.Delete
+func (mmDelete *mThingImageRepositoryMockDelete) Inspect(f func(ctx context.Context, imageID int, tx *sql.Tx)) *mThingImageRepositoryMockDelete {
+	if mmDelete.mock.inspectFuncDelete != nil {
+		mmDelete.mock.t.Fatalf("Inspect function is already set for ThingImageRepositoryMock.Delete")
+	}
+
+	mmDelete.mock.inspectFuncDelete = f
+
+	return mmDelete
+}
+
+// Return sets up results that will be returned by ThingImageRepository.Delete
+func (mmDelete *mThingImageRepositoryMockDelete) Return(err error) *ThingImageRepositoryMock {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("ThingImageRepositoryMock.Delete mock is already set by Set")
+	}
+
+	if mmDelete.defaultExpectation == nil {
+		mmDelete.defaultExpectation = &ThingImageRepositoryMockDeleteExpectation{mock: mmDelete.mock}
+	}
+	mmDelete.defaultExpectation.results = &ThingImageRepositoryMockDeleteResults{err}
+	return mmDelete.mock
+}
+
+// Set uses given function f to mock the ThingImageRepository.Delete method
+func (mmDelete *mThingImageRepositoryMockDelete) Set(f func(ctx context.Context, imageID int, tx *sql.Tx) (err error)) *ThingImageRepositoryMock {
+	if mmDelete.defaultExpectation != nil {
+		mmDelete.mock.t.Fatalf("Default expectation is already set for the ThingImageRepository.Delete method")
+	}
+
+	if len(mmDelete.expectations) > 0 {
+		mmDelete.mock.t.Fatalf("Some expectations are already set for the ThingImageRepository.Delete method")
+	}
+
+	mmDelete.mock.funcDelete = f
+	return mmDelete.mock
+}
+
+// When sets expectation for the ThingImageRepository.Delete which will trigger the result defined by the following
+// Then helper
+func (mmDelete *mThingImageRepositoryMockDelete) When(ctx context.Context, imageID int, tx *sql.Tx) *ThingImageRepositoryMockDeleteExpectation {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("ThingImageRepositoryMock.Delete mock is already set by Set")
+	}
+
+	expectation := &ThingImageRepositoryMockDeleteExpectation{
+		mock:   mmDelete.mock,
+		params: &ThingImageRepositoryMockDeleteParams{ctx, imageID, tx},
+	}
+	mmDelete.expectations = append(mmDelete.expectations, expectation)
+	return expectation
+}
+
+// Then sets up ThingImageRepository.Delete return parameters for the expectation previously defined by the When method
+func (e *ThingImageRepositoryMockDeleteExpectation) Then(err error) *ThingImageRepositoryMock {
+	e.results = &ThingImageRepositoryMockDeleteResults{err}
+	return e.mock
+}
+
+// Times sets number of times ThingImageRepository.Delete should be invoked
+func (mmDelete *mThingImageRepositoryMockDelete) Times(n uint64) *mThingImageRepositoryMockDelete {
+	if n == 0 {
+		mmDelete.mock.t.Fatalf("Times of ThingImageRepositoryMock.Delete mock can not be zero")
+	}
+	mm_atomic.StoreUint64(&mmDelete.expectedInvocations, n)
+	return mmDelete
+}
+
+func (mmDelete *mThingImageRepositoryMockDelete) invocationsDone() bool {
+	if len(mmDelete.expectations) == 0 && mmDelete.defaultExpectation == nil && mmDelete.mock.funcDelete == nil {
+		return true
+	}
+
+	totalInvocations := mm_atomic.LoadUint64(&mmDelete.mock.afterDeleteCounter)
+	expectedInvocations := mm_atomic.LoadUint64(&mmDelete.expectedInvocations)
+
+	return totalInvocations > 0 && (expectedInvocations == 0 || expectedInvocations == totalInvocations)
+}
+
+// Delete implements thing.ThingImageRepository
+func (mmDelete *ThingImageRepositoryMock) Delete(ctx context.Context, imageID int, tx *sql.Tx) (err error) {
+	mm_atomic.AddUint64(&mmDelete.beforeDeleteCounter, 1)
+	defer mm_atomic.AddUint64(&mmDelete.afterDeleteCounter, 1)
+
+	if mmDelete.inspectFuncDelete != nil {
+		mmDelete.inspectFuncDelete(ctx, imageID, tx)
+	}
+
+	mm_params := ThingImageRepositoryMockDeleteParams{ctx, imageID, tx}
+
+	// Record call args
+	mmDelete.DeleteMock.mutex.Lock()
+	mmDelete.DeleteMock.callArgs = append(mmDelete.DeleteMock.callArgs, &mm_params)
+	mmDelete.DeleteMock.mutex.Unlock()
+
+	for _, e := range mmDelete.DeleteMock.expectations {
+		if minimock.Equal(*e.params, mm_params) {
+			mm_atomic.AddUint64(&e.Counter, 1)
+			return e.results.err
+		}
+	}
+
+	if mmDelete.DeleteMock.defaultExpectation != nil {
+		mm_atomic.AddUint64(&mmDelete.DeleteMock.defaultExpectation.Counter, 1)
+		mm_want := mmDelete.DeleteMock.defaultExpectation.params
+		mm_want_ptrs := mmDelete.DeleteMock.defaultExpectation.paramPtrs
+
+		mm_got := ThingImageRepositoryMockDeleteParams{ctx, imageID, tx}
+
+		if mm_want_ptrs != nil {
+
+			if mm_want_ptrs.ctx != nil && !minimock.Equal(*mm_want_ptrs.ctx, mm_got.ctx) {
+				mmDelete.t.Errorf("ThingImageRepositoryMock.Delete got unexpected parameter ctx, want: %#v, got: %#v%s\n", *mm_want_ptrs.ctx, mm_got.ctx, minimock.Diff(*mm_want_ptrs.ctx, mm_got.ctx))
+			}
+
+			if mm_want_ptrs.imageID != nil && !minimock.Equal(*mm_want_ptrs.imageID, mm_got.imageID) {
+				mmDelete.t.Errorf("ThingImageRepositoryMock.Delete got unexpected parameter imageID, want: %#v, got: %#v%s\n", *mm_want_ptrs.imageID, mm_got.imageID, minimock.Diff(*mm_want_ptrs.imageID, mm_got.imageID))
+			}
+
+			if mm_want_ptrs.tx != nil && !minimock.Equal(*mm_want_ptrs.tx, mm_got.tx) {
+				mmDelete.t.Errorf("ThingImageRepositoryMock.Delete got unexpected parameter tx, want: %#v, got: %#v%s\n", *mm_want_ptrs.tx, mm_got.tx, minimock.Diff(*mm_want_ptrs.tx, mm_got.tx))
+			}
+
+		} else if mm_want != nil && !minimock.Equal(*mm_want, mm_got) {
+			mmDelete.t.Errorf("ThingImageRepositoryMock.Delete got unexpected parameters, want: %#v, got: %#v%s\n", *mm_want, mm_got, minimock.Diff(*mm_want, mm_got))
+		}
+
+		mm_results := mmDelete.DeleteMock.defaultExpectation.results
+		if mm_results == nil {
+			mmDelete.t.Fatal("No results are set for the ThingImageRepositoryMock.Delete")
+		}
+		return (*mm_results).err
+	}
+	if mmDelete.funcDelete != nil {
+		return mmDelete.funcDelete(ctx, imageID, tx)
+	}
+	mmDelete.t.Fatalf("Unexpected call to ThingImageRepositoryMock.Delete. %v %v %v", ctx, imageID, tx)
+	return
+}
+
+// DeleteAfterCounter returns a count of finished ThingImageRepositoryMock.Delete invocations
+func (mmDelete *ThingImageRepositoryMock) DeleteAfterCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmDelete.afterDeleteCounter)
+}
+
+// DeleteBeforeCounter returns a count of ThingImageRepositoryMock.Delete invocations
+func (mmDelete *ThingImageRepositoryMock) DeleteBeforeCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmDelete.beforeDeleteCounter)
+}
+
+// Calls returns a list of arguments used in each call to ThingImageRepositoryMock.Delete.
+// The list is in the same order as the calls were made (i.e. recent calls have a higher index)
+func (mmDelete *mThingImageRepositoryMockDelete) Calls() []*ThingImageRepositoryMockDeleteParams {
+	mmDelete.mutex.RLock()
+
+	argCopy := make([]*ThingImageRepositoryMockDeleteParams, len(mmDelete.callArgs))
+	copy(argCopy, mmDelete.callArgs)
+
+	mmDelete.mutex.RUnlock()
+
+	return argCopy
+}
+
+// MinimockDeleteDone returns true if the count of the Delete invocations corresponds
+// the number of defined expectations
+func (m *ThingImageRepositoryMock) MinimockDeleteDone() bool {
+	if m.DeleteMock.optional {
+		// Optional methods provide '0 or more' call count restriction.
+		return true
+	}
+
+	for _, e := range m.DeleteMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			return false
+		}
+	}
+
+	return m.DeleteMock.invocationsDone()
+}
+
+// MinimockDeleteInspect logs each unmet expectation
+func (m *ThingImageRepositoryMock) MinimockDeleteInspect() {
+	for _, e := range m.DeleteMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			m.t.Errorf("Expected call to ThingImageRepositoryMock.Delete with params: %#v", *e.params)
+		}
+	}
+
+	afterDeleteCounter := mm_atomic.LoadUint64(&m.afterDeleteCounter)
+	// if default expectation was set then invocations count should be greater than zero
+	if m.DeleteMock.defaultExpectation != nil && afterDeleteCounter < 1 {
+		if m.DeleteMock.defaultExpectation.params == nil {
+			m.t.Error("Expected call to ThingImageRepositoryMock.Delete")
+		} else {
+			m.t.Errorf("Expected call to ThingImageRepositoryMock.Delete with params: %#v", *m.DeleteMock.defaultExpectation.params)
+		}
+	}
+	// if func was set then invocations count should be greater than zero
+	if m.funcDelete != nil && afterDeleteCounter < 1 {
+		m.t.Error("Expected call to ThingImageRepositoryMock.Delete")
+	}
+
+	if !m.DeleteMock.invocationsDone() && afterDeleteCounter > 0 {
+		m.t.Errorf("Expected %d calls to ThingImageRepositoryMock.Delete but found %d calls",
+			mm_atomic.LoadUint64(&m.DeleteMock.expectedInvocations), afterDeleteCounter)
+	}
+}
+
+type mThingImageRepositoryMockGetByThingID struct {
+	optional           bool
+	mock               *ThingImageRepositoryMock
+	defaultExpectation *ThingImageRepositoryMockGetByThingIDExpectation
+	expectations       []*ThingImageRepositoryMockGetByThingIDExpectation
+
+	callArgs []*ThingImageRepositoryMockGetByThingIDParams
+	mutex    sync.RWMutex
+
+	expectedInvocations uint64
+}
+
+// ThingImageRepositoryMockGetByThingIDExpectation specifies expectation struct of the ThingImageRepository.GetByThingID
+type ThingImageRepositoryMockGetByThingIDExpectation struct {
+	mock      *ThingImageRepositoryMock
+	params    *ThingImageRepositoryMockGetByThingIDParams
+	paramPtrs *ThingImageRepositoryMockGetByThingIDParamPtrs
+	results   *ThingImageRepositoryMockGetByThingIDResults
+	Counter   uint64
+}
+
+// ThingImageRepositoryMockGetByThingIDParams contains parameters of the ThingImageRepository.GetByThingID
+type ThingImageRepositoryMockGetByThingIDParams struct {
+	ctx     context.Context
+	thingID int
+}
+
+// ThingImageRepositoryMockGetByThingIDParamPtrs contains pointers to parameters of the ThingImageRepository.GetByThingID
+type ThingImageRepositoryMockGetByThingIDParamPtrs struct {
+	ctx     *context.Context
+	thingID *int
+}
+
+// ThingImageRepositoryMockGetByThingIDResults contains results of the ThingImageRepository.GetByThingID
+type ThingImageRepositoryMockGetByThingIDResults struct {
+	ia1 []models.Image
+	err error
+}
+
+// Marks this method to be optional. The default behavior of any method with Return() is '1 or more', meaning
+// the test will fail minimock's automatic final call check if the mocked method was not called at least once.
+// Optional() makes method check to work in '0 or more' mode.
+// It is NOT RECOMMENDED to use this option unless you really need it, as default behaviour helps to
+// catch the problems when the expected method call is totally skipped during test run.
+func (mmGetByThingID *mThingImageRepositoryMockGetByThingID) Optional() *mThingImageRepositoryMockGetByThingID {
+	mmGetByThingID.optional = true
+	return mmGetByThingID
+}
+
+// Expect sets up expected params for ThingImageRepository.GetByThingID
+func (mmGetByThingID *mThingImageRepositoryMockGetByThingID) Expect(ctx context.Context, thingID int) *mThingImageRepositoryMockGetByThingID {
+	if mmGetByThingID.mock.funcGetByThingID != nil {
+		mmGetByThingID.mock.t.Fatalf("ThingImageRepositoryMock.GetByThingID mock is already set by Set")
+	}
+
+	if mmGetByThingID.defaultExpectation == nil {
+		mmGetByThingID.defaultExpectation = &ThingImageRepositoryMockGetByThingIDExpectation{}
+	}
+
+	if mmGetByThingID.defaultExpectation.paramPtrs != nil {
+		mmGetByThingID.mock.t.Fatalf("ThingImageRepositoryMock.GetByThingID mock is already set by ExpectParams functions")
+	}
+
+	mmGetByThingID.defaultExpectation.params = &ThingImageRepositoryMockGetByThingIDParams{ctx, thingID}
+	for _, e := range mmGetByThingID.expectations {
+		if minimock.Equal(e.params, mmGetByThingID.defaultExpectation.params) {
+			mmGetByThingID.mock.t.Fatalf("Expectation set by When has same params: %#v", *mmGetByThingID.defaultExpectation.params)
+		}
+	}
+
+	return mmGetByThingID
+}
+
+// ExpectCtxParam1 sets up expected param ctx for ThingImageRepository.GetByThingID
+func (mmGetByThingID *mThingImageRepositoryMockGetByThingID) ExpectCtxParam1(ctx context.Context) *mThingImageRepositoryMockGetByThingID {
+	if mmGetByThingID.mock.funcGetByThingID != nil {
+		mmGetByThingID.mock.t.Fatalf("ThingImageRepositoryMock.GetByThingID mock is already set by Set")
+	}
+
+	if mmGetByThingID.defaultExpectation == nil {
+		mmGetByThingID.defaultExpectation = &ThingImageRepositoryMockGetByThingIDExpectation{}
+	}
+
+	if mmGetByThingID.defaultExpectation.params != nil {
+		mmGetByThingID.mock.t.Fatalf("ThingImageRepositoryMock.GetByThingID mock is already set by Expect")
+	}
+
+	if mmGetByThingID.defaultExpectation.paramPtrs == nil {
+		mmGetByThingID.defaultExpectation.paramPtrs = &ThingImageRepositoryMockGetByThingIDParamPtrs{}
+	}
+	mmGetByThingID.defaultExpectation.paramPtrs.ctx = &ctx
+
+	return mmGetByThingID
+}
+
+// ExpectThingIDParam2 sets up expected param thingID for ThingImageRepository.GetByThingID
+func (mmGetByThingID *mThingImageRepositoryMockGetByThingID) ExpectThingIDParam2(thingID int) *mThingImageRepositoryMockGetByThingID {
+	if mmGetByThingID.mock.funcGetByThingID != nil {
+		mmGetByThingID.mock.t.Fatalf("ThingImageRepositoryMock.GetByThingID mock is already set by Set")
+	}
+
+	if mmGetByThingID.defaultExpectation == nil {
+		mmGetByThingID.defaultExpectation = &ThingImageRepositoryMockGetByThingIDExpectation{}
+	}
+
+	if mmGetByThingID.defaultExpectation.params != nil {
+		mmGetByThingID.mock.t.Fatalf("ThingImageRepositoryMock.GetByThingID mock is already set by Expect")
+	}
+
+	if mmGetByThingID.defaultExpectation.paramPtrs == nil {
+		mmGetByThingID.defaultExpectation.paramPtrs = &ThingImageRepositoryMockGetByThingIDParamPtrs{}
+	}
+	mmGetByThingID.defaultExpectation.paramPtrs.thingID = &thingID
+
+	return mmGetByThingID
+}
+
+// Inspect accepts an inspector function that has same arguments as the ThingImageRepository.GetByThingID
+func (mmGetByThingID *mThingImageRepositoryMockGetByThingID) Inspect(f func(ctx context.Context, thingID int)) *mThingImageRepositoryMockGetByThingID {
+	if mmGetByThingID.mock.inspectFuncGetByThingID != nil {
+		mmGetByThingID.mock.t.Fatalf("Inspect function is already set for ThingImageRepositoryMock.GetByThingID")
+	}
+
+	mmGetByThingID.mock.inspectFuncGetByThingID = f
+
+	return mmGetByThingID
+}
+
+// Return sets up results that will be returned by ThingImageRepository.GetByThingID
+func (mmGetByThingID *mThingImageRepositoryMockGetByThingID) Return(ia1 []models.Image, err error) *ThingImageRepositoryMock {
+	if mmGetByThingID.mock.funcGetByThingID != nil {
+		mmGetByThingID.mock.t.Fatalf("ThingImageRepositoryMock.GetByThingID mock is already set by Set")
+	}
+
+	if mmGetByThingID.defaultExpectation == nil {
+		mmGetByThingID.defaultExpectation = &ThingImageRepositoryMockGetByThingIDExpectation{mock: mmGetByThingID.mock}
+	}
+	mmGetByThingID.defaultExpectation.results = &ThingImageRepositoryMockGetByThingIDResults{ia1, err}
+	return mmGetByThingID.mock
+}
+
+// Set uses given function f to mock the ThingImageRepository.GetByThingID method
+func (mmGetByThingID *mThingImageRepositoryMockGetByThingID) Set(f func(ctx context.Context, thingID int) (ia1 []models.Image, err error)) *ThingImageRepositoryMock {
+	if mmGetByThingID.defaultExpectation != nil {
+		mmGetByThingID.mock.t.Fatalf("Default expectation is already set for the ThingImageRepository.GetByThingID method")
+	}
+
+	if len(mmGetByThingID.expectations) > 0 {
+		mmGetByThingID.mock.t.Fatalf("Some expectations are already set for the ThingImageRepository.GetByThingID method")
+	}
+
+	mmGetByThingID.mock.funcGetByThingID = f
+	return mmGetByThingID.mock
+}
+
+// When sets expectation for the ThingImageRepository.GetByThingID which will trigger the result defined by the following
+// Then helper
+func (mmGetByThingID *mThingImageRepositoryMockGetByThingID) When(ctx context.Context, thingID int) *ThingImageRepositoryMockGetByThingIDExpectation {
+	if mmGetByThingID.mock.funcGetByThingID != nil {
+		mmGetByThingID.mock.t.Fatalf("ThingImageRepositoryMock.GetByThingID mock is already set by Set")
+	}
+
+	expectation := &ThingImageRepositoryMockGetByThingIDExpectation{
+		mock:   mmGetByThingID.mock,
+		params: &ThingImageRepositoryMockGetByThingIDParams{ctx, thingID},
+	}
+	mmGetByThingID.expectations = append(mmGetByThingID.expectations, expectation)
+	return expectation
+}
+
+// Then sets up ThingImageRepository.GetByThingID return parameters for the expectation previously defined by the When method
+func (e *ThingImageRepositoryMockGetByThingIDExpectation) Then(ia1 []models.Image, err error) *ThingImageRepositoryMock {
+	e.results = &ThingImageRepositoryMockGetByThingIDResults{ia1, err}
+	return e.mock
+}
+
+// Times sets number of times ThingImageRepository.GetByThingID should be invoked
+func (mmGetByThingID *mThingImageRepositoryMockGetByThingID) Times(n uint64) *mThingImageRepositoryMockGetByThingID {
+	if n == 0 {
+		mmGetByThingID.mock.t.Fatalf("Times of ThingImageRepositoryMock.GetByThingID mock can not be zero")
+	}
+	mm_atomic.StoreUint64(&mmGetByThingID.expectedInvocations, n)
+	return mmGetByThingID
+}
+
+func (mmGetByThingID *mThingImageRepositoryMockGetByThingID) invocationsDone() bool {
+	if len(mmGetByThingID.expectations) == 0 && mmGetByThingID.defaultExpectation == nil && mmGetByThingID.mock.funcGetByThingID == nil {
+		return true
+	}
+
+	totalInvocations := mm_atomic.LoadUint64(&mmGetByThingID.mock.afterGetByThingIDCounter)
+	expectedInvocations := mm_atomic.LoadUint64(&mmGetByThingID.expectedInvocations)
+
+	return totalInvocations > 0 && (expectedInvocations == 0 || expectedInvocations == totalInvocations)
+}
+
+// GetByThingID implements thing.ThingImageRepository
+func (mmGetByThingID *ThingImageRepositoryMock) GetByThingID(ctx context.Context, thingID int) (ia1 []models.Image, err error) {
+	mm_atomic.AddUint64(&mmGetByThingID.beforeGetByThingIDCounter, 1)
+	defer mm_atomic.AddUint64(&mmGetByThingID.afterGetByThingIDCounter, 1)
+
+	if mmGetByThingID.inspectFuncGetByThingID != nil {
+		mmGetByThingID.inspectFuncGetByThingID(ctx, thingID)
+	}
+
+	mm_params := ThingImageRepositoryMockGetByThingIDParams{ctx, thingID}
+
+	// Record call args
+	mmGetByThingID.GetByThingIDMock.mutex.Lock()
+	mmGetByThingID.GetByThingIDMock.callArgs = append(mmGetByThingID.GetByThingIDMock.callArgs, &mm_params)
+	mmGetByThingID.GetByThingIDMock.mutex.Unlock()
+
+	for _, e := range mmGetByThingID.GetByThingIDMock.expectations {
+		if minimock.Equal(*e.params, mm_params) {
+			mm_atomic.AddUint64(&e.Counter, 1)
+			return e.results.ia1, e.results.err
+		}
+	}
+
+	if mmGetByThingID.GetByThingIDMock.defaultExpectation != nil {
+		mm_atomic.AddUint64(&mmGetByThingID.GetByThingIDMock.defaultExpectation.Counter, 1)
+		mm_want := mmGetByThingID.GetByThingIDMock.defaultExpectation.params
+		mm_want_ptrs := mmGetByThingID.GetByThingIDMock.defaultExpectation.paramPtrs
+
+		mm_got := ThingImageRepositoryMockGetByThingIDParams{ctx, thingID}
+
+		if mm_want_ptrs != nil {
+
+			if mm_want_ptrs.ctx != nil && !minimock.Equal(*mm_want_ptrs.ctx, mm_got.ctx) {
+				mmGetByThingID.t.Errorf("ThingImageRepositoryMock.GetByThingID got unexpected parameter ctx, want: %#v, got: %#v%s\n", *mm_want_ptrs.ctx, mm_got.ctx, minimock.Diff(*mm_want_ptrs.ctx, mm_got.ctx))
+			}
+
+			if mm_want_ptrs.thingID != nil && !minimock.Equal(*mm_want_ptrs.thingID, mm_got.thingID) {
+				mmGetByThingID.t.Errorf("ThingImageRepositoryMock.GetByThingID got unexpected parameter thingID, want: %#v, got: %#v%s\n", *mm_want_ptrs.thingID, mm_got.thingID, minimock.Diff(*mm_want_ptrs.thingID, mm_got.thingID))
+			}
+
+		} else if mm_want != nil && !minimock.Equal(*mm_want, mm_got) {
+			mmGetByThingID.t.Errorf("ThingImageRepositoryMock.GetByThingID got unexpected parameters, want: %#v, got: %#v%s\n", *mm_want, mm_got, minimock.Diff(*mm_want, mm_got))
+		}
+
+		mm_results := mmGetByThingID.GetByThingIDMock.defaultExpectation.results
+		if mm_results == nil {
+			mmGetByThingID.t.Fatal("No results are set for the ThingImageRepositoryMock.GetByThingID")
+		}
+		return (*mm_results).ia1, (*mm_results).err
+	}
+	if mmGetByThingID.funcGetByThingID != nil {
+		return mmGetByThingID.funcGetByThingID(ctx, thingID)
+	}
+	mmGetByThingID.t.Fatalf("Unexpected call to ThingImageRepositoryMock.GetByThingID. %v %v", ctx, thingID)
+	return
+}
+
+// GetByThingIDAfterCounter returns a count of finished ThingImageRepositoryMock.GetByThingID invocations
+func (mmGetByThingID *ThingImageRepositoryMock) GetByThingIDAfterCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmGetByThingID.afterGetByThingIDCounter)
+}
+
+// GetByThingIDBeforeCounter returns a count of ThingImageRepositoryMock.GetByThingID invocations
+func (mmGetByThingID *ThingImageRepositoryMock) GetByThingIDBeforeCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmGetByThingID.beforeGetByThingIDCounter)
+}
+
+// Calls returns a list of arguments used in each call to ThingImageRepositoryMock.GetByThingID.
+// The list is in the same order as the calls were made (i.e. recent calls have a higher index)
+func (mmGetByThingID *mThingImageRepositoryMockGetByThingID) Calls() []*ThingImageRepositoryMockGetByThingIDParams {
+	mmGetByThingID.mutex.RLock()
+
+	argCopy := make([]*ThingImageRepositoryMockGetByThingIDParams, len(mmGetByThingID.callArgs))
+	copy(argCopy, mmGetByThingID.callArgs)
+
+	mmGetByThingID.mutex.RUnlock()
+
+	return argCopy
+}
+
+// MinimockGetByThingIDDone returns true if the count of the GetByThingID invocations corresponds
+// the number of defined expectations
+func (m *ThingImageRepositoryMock) MinimockGetByThingIDDone() bool {
+	if m.GetByThingIDMock.optional {
+		// Optional methods provide '0 or more' call count restriction.
+		return true
+	}
+
+	for _, e := range m.GetByThingIDMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			return false
+		}
+	}
+
+	return m.GetByThingIDMock.invocationsDone()
+}
+
+// MinimockGetByThingIDInspect logs each unmet expectation
+func (m *ThingImageRepositoryMock) MinimockGetByThingIDInspect() {
+	for _, e := range m.GetByThingIDMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			m.t.Errorf("Expected call to ThingImageRepositoryMock.GetByThingID with params: %#v", *e.params)
+		}
+	}
+
+	afterGetByThingIDCounter := mm_atomic.LoadUint64(&m.afterGetByThingIDCounter)
+	// if default expectation was set then invocations count should be greater than zero
+	if m.GetByThingIDMock.defaultExpectation != nil && afterGetByThingIDCounter < 1 {
+		if m.GetByThingIDMock.defaultExpectation.params == nil {
+			m.t.Error("Expected call to ThingImageRepositoryMock.GetByThingID")
+		} else {
+			m.t.Errorf("Expected call to ThingImageRepositoryMock.GetByThingID with params: %#v", *m.GetByThingIDMock.defaultExpectation.params)
+		}
+	}
+	// if func was set then invocations count should be greater than zero
+	if m.funcGetByThingID != nil && afterGetByThingIDCounter < 1 {
+		m.t.Error("Expected call to ThingImageRepositoryMock.GetByThingID")
+	}
+
+	if !m.GetByThingIDMock.invocationsDone() && afterGetByThingIDCounter > 0 {
+		m.t.Errorf("Expected %d calls to ThingImageRepositoryMock.GetByThingID but found %d calls",
+			mm_atomic.LoadUint64(&m.GetByThingIDMock.expectedInvocations), afterGetByThingIDCounter)
+	}
+}
+
+// MinimockFinish checks that all mocked methods have been called the expected number of times
+func (m *ThingImageRepositoryMock) MinimockFinish() {
+	m.finishOnce.Do(func() {
+		if !m.minimockDone() {
+			m.MinimockDeleteInspect()
+
+			m.MinimockGetByThingIDInspect()
+		}
+	})
+}
+
+// MinimockWait waits for all mocked methods to be called the expected number of times
+func (m *ThingImageRepositoryMock) MinimockWait(timeout mm_time.Duration) {
+	timeoutCh := mm_time.After(timeout)
+	for {
+		if m.minimockDone() {
+			return
+		}
+		select {
+		case <-timeoutCh:
+			m.MinimockFinish()
+			return
+		case <-mm_time.After(10 * mm_time.Millisecond):
+		}
+	}
+}
+
+func (m *ThingImageRepositoryMock) minimockDone() bool {
+	done := true
+	return done &&
+		m.MinimockDeleteDone() &&
+		m.MinimockGetByThingIDDone()
+}

+ 422 - 0
internal/api/v1/thing/mocks/thing_notification_repository_minimock.go

@@ -0,0 +1,422 @@
+// Code generated by http://github.com/gojuno/minimock (v3.3.13). DO NOT EDIT.
+
+package mocks
+
+//go:generate minimock -i git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/thing.ThingNotificationRepository -o thing_notification_repository_minimock.go -n ThingNotificationRepositoryMock -p mocks
+
+import (
+	"context"
+	"database/sql"
+	"sync"
+	mm_atomic "sync/atomic"
+	mm_time "time"
+
+	"github.com/gojuno/minimock/v3"
+)
+
+// ThingNotificationRepositoryMock implements thing.ThingNotificationRepository
+type ThingNotificationRepositoryMock struct {
+	t          minimock.Tester
+	finishOnce sync.Once
+
+	funcDelete          func(ctx context.Context, thingID int, tx *sql.Tx) (err error)
+	inspectFuncDelete   func(ctx context.Context, thingID int, tx *sql.Tx)
+	afterDeleteCounter  uint64
+	beforeDeleteCounter uint64
+	DeleteMock          mThingNotificationRepositoryMockDelete
+}
+
+// NewThingNotificationRepositoryMock returns a mock for thing.ThingNotificationRepository
+func NewThingNotificationRepositoryMock(t minimock.Tester) *ThingNotificationRepositoryMock {
+	m := &ThingNotificationRepositoryMock{t: t}
+
+	if controller, ok := t.(minimock.MockController); ok {
+		controller.RegisterMocker(m)
+	}
+
+	m.DeleteMock = mThingNotificationRepositoryMockDelete{mock: m}
+	m.DeleteMock.callArgs = []*ThingNotificationRepositoryMockDeleteParams{}
+
+	t.Cleanup(m.MinimockFinish)
+
+	return m
+}
+
+type mThingNotificationRepositoryMockDelete struct {
+	optional           bool
+	mock               *ThingNotificationRepositoryMock
+	defaultExpectation *ThingNotificationRepositoryMockDeleteExpectation
+	expectations       []*ThingNotificationRepositoryMockDeleteExpectation
+
+	callArgs []*ThingNotificationRepositoryMockDeleteParams
+	mutex    sync.RWMutex
+
+	expectedInvocations uint64
+}
+
+// ThingNotificationRepositoryMockDeleteExpectation specifies expectation struct of the ThingNotificationRepository.Delete
+type ThingNotificationRepositoryMockDeleteExpectation struct {
+	mock      *ThingNotificationRepositoryMock
+	params    *ThingNotificationRepositoryMockDeleteParams
+	paramPtrs *ThingNotificationRepositoryMockDeleteParamPtrs
+	results   *ThingNotificationRepositoryMockDeleteResults
+	Counter   uint64
+}
+
+// ThingNotificationRepositoryMockDeleteParams contains parameters of the ThingNotificationRepository.Delete
+type ThingNotificationRepositoryMockDeleteParams struct {
+	ctx     context.Context
+	thingID int
+	tx      *sql.Tx
+}
+
+// ThingNotificationRepositoryMockDeleteParamPtrs contains pointers to parameters of the ThingNotificationRepository.Delete
+type ThingNotificationRepositoryMockDeleteParamPtrs struct {
+	ctx     *context.Context
+	thingID *int
+	tx      **sql.Tx
+}
+
+// ThingNotificationRepositoryMockDeleteResults contains results of the ThingNotificationRepository.Delete
+type ThingNotificationRepositoryMockDeleteResults struct {
+	err error
+}
+
+// Marks this method to be optional. The default behavior of any method with Return() is '1 or more', meaning
+// the test will fail minimock's automatic final call check if the mocked method was not called at least once.
+// Optional() makes method check to work in '0 or more' mode.
+// It is NOT RECOMMENDED to use this option unless you really need it, as default behaviour helps to
+// catch the problems when the expected method call is totally skipped during test run.
+func (mmDelete *mThingNotificationRepositoryMockDelete) Optional() *mThingNotificationRepositoryMockDelete {
+	mmDelete.optional = true
+	return mmDelete
+}
+
+// Expect sets up expected params for ThingNotificationRepository.Delete
+func (mmDelete *mThingNotificationRepositoryMockDelete) Expect(ctx context.Context, thingID int, tx *sql.Tx) *mThingNotificationRepositoryMockDelete {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("ThingNotificationRepositoryMock.Delete mock is already set by Set")
+	}
+
+	if mmDelete.defaultExpectation == nil {
+		mmDelete.defaultExpectation = &ThingNotificationRepositoryMockDeleteExpectation{}
+	}
+
+	if mmDelete.defaultExpectation.paramPtrs != nil {
+		mmDelete.mock.t.Fatalf("ThingNotificationRepositoryMock.Delete mock is already set by ExpectParams functions")
+	}
+
+	mmDelete.defaultExpectation.params = &ThingNotificationRepositoryMockDeleteParams{ctx, thingID, tx}
+	for _, e := range mmDelete.expectations {
+		if minimock.Equal(e.params, mmDelete.defaultExpectation.params) {
+			mmDelete.mock.t.Fatalf("Expectation set by When has same params: %#v", *mmDelete.defaultExpectation.params)
+		}
+	}
+
+	return mmDelete
+}
+
+// ExpectCtxParam1 sets up expected param ctx for ThingNotificationRepository.Delete
+func (mmDelete *mThingNotificationRepositoryMockDelete) ExpectCtxParam1(ctx context.Context) *mThingNotificationRepositoryMockDelete {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("ThingNotificationRepositoryMock.Delete mock is already set by Set")
+	}
+
+	if mmDelete.defaultExpectation == nil {
+		mmDelete.defaultExpectation = &ThingNotificationRepositoryMockDeleteExpectation{}
+	}
+
+	if mmDelete.defaultExpectation.params != nil {
+		mmDelete.mock.t.Fatalf("ThingNotificationRepositoryMock.Delete mock is already set by Expect")
+	}
+
+	if mmDelete.defaultExpectation.paramPtrs == nil {
+		mmDelete.defaultExpectation.paramPtrs = &ThingNotificationRepositoryMockDeleteParamPtrs{}
+	}
+	mmDelete.defaultExpectation.paramPtrs.ctx = &ctx
+
+	return mmDelete
+}
+
+// ExpectThingIDParam2 sets up expected param thingID for ThingNotificationRepository.Delete
+func (mmDelete *mThingNotificationRepositoryMockDelete) ExpectThingIDParam2(thingID int) *mThingNotificationRepositoryMockDelete {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("ThingNotificationRepositoryMock.Delete mock is already set by Set")
+	}
+
+	if mmDelete.defaultExpectation == nil {
+		mmDelete.defaultExpectation = &ThingNotificationRepositoryMockDeleteExpectation{}
+	}
+
+	if mmDelete.defaultExpectation.params != nil {
+		mmDelete.mock.t.Fatalf("ThingNotificationRepositoryMock.Delete mock is already set by Expect")
+	}
+
+	if mmDelete.defaultExpectation.paramPtrs == nil {
+		mmDelete.defaultExpectation.paramPtrs = &ThingNotificationRepositoryMockDeleteParamPtrs{}
+	}
+	mmDelete.defaultExpectation.paramPtrs.thingID = &thingID
+
+	return mmDelete
+}
+
+// ExpectTxParam3 sets up expected param tx for ThingNotificationRepository.Delete
+func (mmDelete *mThingNotificationRepositoryMockDelete) ExpectTxParam3(tx *sql.Tx) *mThingNotificationRepositoryMockDelete {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("ThingNotificationRepositoryMock.Delete mock is already set by Set")
+	}
+
+	if mmDelete.defaultExpectation == nil {
+		mmDelete.defaultExpectation = &ThingNotificationRepositoryMockDeleteExpectation{}
+	}
+
+	if mmDelete.defaultExpectation.params != nil {
+		mmDelete.mock.t.Fatalf("ThingNotificationRepositoryMock.Delete mock is already set by Expect")
+	}
+
+	if mmDelete.defaultExpectation.paramPtrs == nil {
+		mmDelete.defaultExpectation.paramPtrs = &ThingNotificationRepositoryMockDeleteParamPtrs{}
+	}
+	mmDelete.defaultExpectation.paramPtrs.tx = &tx
+
+	return mmDelete
+}
+
+// Inspect accepts an inspector function that has same arguments as the ThingNotificationRepository.Delete
+func (mmDelete *mThingNotificationRepositoryMockDelete) Inspect(f func(ctx context.Context, thingID int, tx *sql.Tx)) *mThingNotificationRepositoryMockDelete {
+	if mmDelete.mock.inspectFuncDelete != nil {
+		mmDelete.mock.t.Fatalf("Inspect function is already set for ThingNotificationRepositoryMock.Delete")
+	}
+
+	mmDelete.mock.inspectFuncDelete = f
+
+	return mmDelete
+}
+
+// Return sets up results that will be returned by ThingNotificationRepository.Delete
+func (mmDelete *mThingNotificationRepositoryMockDelete) Return(err error) *ThingNotificationRepositoryMock {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("ThingNotificationRepositoryMock.Delete mock is already set by Set")
+	}
+
+	if mmDelete.defaultExpectation == nil {
+		mmDelete.defaultExpectation = &ThingNotificationRepositoryMockDeleteExpectation{mock: mmDelete.mock}
+	}
+	mmDelete.defaultExpectation.results = &ThingNotificationRepositoryMockDeleteResults{err}
+	return mmDelete.mock
+}
+
+// Set uses given function f to mock the ThingNotificationRepository.Delete method
+func (mmDelete *mThingNotificationRepositoryMockDelete) Set(f func(ctx context.Context, thingID int, tx *sql.Tx) (err error)) *ThingNotificationRepositoryMock {
+	if mmDelete.defaultExpectation != nil {
+		mmDelete.mock.t.Fatalf("Default expectation is already set for the ThingNotificationRepository.Delete method")
+	}
+
+	if len(mmDelete.expectations) > 0 {
+		mmDelete.mock.t.Fatalf("Some expectations are already set for the ThingNotificationRepository.Delete method")
+	}
+
+	mmDelete.mock.funcDelete = f
+	return mmDelete.mock
+}
+
+// When sets expectation for the ThingNotificationRepository.Delete which will trigger the result defined by the following
+// Then helper
+func (mmDelete *mThingNotificationRepositoryMockDelete) When(ctx context.Context, thingID int, tx *sql.Tx) *ThingNotificationRepositoryMockDeleteExpectation {
+	if mmDelete.mock.funcDelete != nil {
+		mmDelete.mock.t.Fatalf("ThingNotificationRepositoryMock.Delete mock is already set by Set")
+	}
+
+	expectation := &ThingNotificationRepositoryMockDeleteExpectation{
+		mock:   mmDelete.mock,
+		params: &ThingNotificationRepositoryMockDeleteParams{ctx, thingID, tx},
+	}
+	mmDelete.expectations = append(mmDelete.expectations, expectation)
+	return expectation
+}
+
+// Then sets up ThingNotificationRepository.Delete return parameters for the expectation previously defined by the When method
+func (e *ThingNotificationRepositoryMockDeleteExpectation) Then(err error) *ThingNotificationRepositoryMock {
+	e.results = &ThingNotificationRepositoryMockDeleteResults{err}
+	return e.mock
+}
+
+// Times sets number of times ThingNotificationRepository.Delete should be invoked
+func (mmDelete *mThingNotificationRepositoryMockDelete) Times(n uint64) *mThingNotificationRepositoryMockDelete {
+	if n == 0 {
+		mmDelete.mock.t.Fatalf("Times of ThingNotificationRepositoryMock.Delete mock can not be zero")
+	}
+	mm_atomic.StoreUint64(&mmDelete.expectedInvocations, n)
+	return mmDelete
+}
+
+func (mmDelete *mThingNotificationRepositoryMockDelete) invocationsDone() bool {
+	if len(mmDelete.expectations) == 0 && mmDelete.defaultExpectation == nil && mmDelete.mock.funcDelete == nil {
+		return true
+	}
+
+	totalInvocations := mm_atomic.LoadUint64(&mmDelete.mock.afterDeleteCounter)
+	expectedInvocations := mm_atomic.LoadUint64(&mmDelete.expectedInvocations)
+
+	return totalInvocations > 0 && (expectedInvocations == 0 || expectedInvocations == totalInvocations)
+}
+
+// Delete implements thing.ThingNotificationRepository
+func (mmDelete *ThingNotificationRepositoryMock) Delete(ctx context.Context, thingID int, tx *sql.Tx) (err error) {
+	mm_atomic.AddUint64(&mmDelete.beforeDeleteCounter, 1)
+	defer mm_atomic.AddUint64(&mmDelete.afterDeleteCounter, 1)
+
+	if mmDelete.inspectFuncDelete != nil {
+		mmDelete.inspectFuncDelete(ctx, thingID, tx)
+	}
+
+	mm_params := ThingNotificationRepositoryMockDeleteParams{ctx, thingID, tx}
+
+	// Record call args
+	mmDelete.DeleteMock.mutex.Lock()
+	mmDelete.DeleteMock.callArgs = append(mmDelete.DeleteMock.callArgs, &mm_params)
+	mmDelete.DeleteMock.mutex.Unlock()
+
+	for _, e := range mmDelete.DeleteMock.expectations {
+		if minimock.Equal(*e.params, mm_params) {
+			mm_atomic.AddUint64(&e.Counter, 1)
+			return e.results.err
+		}
+	}
+
+	if mmDelete.DeleteMock.defaultExpectation != nil {
+		mm_atomic.AddUint64(&mmDelete.DeleteMock.defaultExpectation.Counter, 1)
+		mm_want := mmDelete.DeleteMock.defaultExpectation.params
+		mm_want_ptrs := mmDelete.DeleteMock.defaultExpectation.paramPtrs
+
+		mm_got := ThingNotificationRepositoryMockDeleteParams{ctx, thingID, tx}
+
+		if mm_want_ptrs != nil {
+
+			if mm_want_ptrs.ctx != nil && !minimock.Equal(*mm_want_ptrs.ctx, mm_got.ctx) {
+				mmDelete.t.Errorf("ThingNotificationRepositoryMock.Delete got unexpected parameter ctx, want: %#v, got: %#v%s\n", *mm_want_ptrs.ctx, mm_got.ctx, minimock.Diff(*mm_want_ptrs.ctx, mm_got.ctx))
+			}
+
+			if mm_want_ptrs.thingID != nil && !minimock.Equal(*mm_want_ptrs.thingID, mm_got.thingID) {
+				mmDelete.t.Errorf("ThingNotificationRepositoryMock.Delete got unexpected parameter thingID, want: %#v, got: %#v%s\n", *mm_want_ptrs.thingID, mm_got.thingID, minimock.Diff(*mm_want_ptrs.thingID, mm_got.thingID))
+			}
+
+			if mm_want_ptrs.tx != nil && !minimock.Equal(*mm_want_ptrs.tx, mm_got.tx) {
+				mmDelete.t.Errorf("ThingNotificationRepositoryMock.Delete got unexpected parameter tx, want: %#v, got: %#v%s\n", *mm_want_ptrs.tx, mm_got.tx, minimock.Diff(*mm_want_ptrs.tx, mm_got.tx))
+			}
+
+		} else if mm_want != nil && !minimock.Equal(*mm_want, mm_got) {
+			mmDelete.t.Errorf("ThingNotificationRepositoryMock.Delete got unexpected parameters, want: %#v, got: %#v%s\n", *mm_want, mm_got, minimock.Diff(*mm_want, mm_got))
+		}
+
+		mm_results := mmDelete.DeleteMock.defaultExpectation.results
+		if mm_results == nil {
+			mmDelete.t.Fatal("No results are set for the ThingNotificationRepositoryMock.Delete")
+		}
+		return (*mm_results).err
+	}
+	if mmDelete.funcDelete != nil {
+		return mmDelete.funcDelete(ctx, thingID, tx)
+	}
+	mmDelete.t.Fatalf("Unexpected call to ThingNotificationRepositoryMock.Delete. %v %v %v", ctx, thingID, tx)
+	return
+}
+
+// DeleteAfterCounter returns a count of finished ThingNotificationRepositoryMock.Delete invocations
+func (mmDelete *ThingNotificationRepositoryMock) DeleteAfterCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmDelete.afterDeleteCounter)
+}
+
+// DeleteBeforeCounter returns a count of ThingNotificationRepositoryMock.Delete invocations
+func (mmDelete *ThingNotificationRepositoryMock) DeleteBeforeCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmDelete.beforeDeleteCounter)
+}
+
+// Calls returns a list of arguments used in each call to ThingNotificationRepositoryMock.Delete.
+// The list is in the same order as the calls were made (i.e. recent calls have a higher index)
+func (mmDelete *mThingNotificationRepositoryMockDelete) Calls() []*ThingNotificationRepositoryMockDeleteParams {
+	mmDelete.mutex.RLock()
+
+	argCopy := make([]*ThingNotificationRepositoryMockDeleteParams, len(mmDelete.callArgs))
+	copy(argCopy, mmDelete.callArgs)
+
+	mmDelete.mutex.RUnlock()
+
+	return argCopy
+}
+
+// MinimockDeleteDone returns true if the count of the Delete invocations corresponds
+// the number of defined expectations
+func (m *ThingNotificationRepositoryMock) MinimockDeleteDone() bool {
+	if m.DeleteMock.optional {
+		// Optional methods provide '0 or more' call count restriction.
+		return true
+	}
+
+	for _, e := range m.DeleteMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			return false
+		}
+	}
+
+	return m.DeleteMock.invocationsDone()
+}
+
+// MinimockDeleteInspect logs each unmet expectation
+func (m *ThingNotificationRepositoryMock) MinimockDeleteInspect() {
+	for _, e := range m.DeleteMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			m.t.Errorf("Expected call to ThingNotificationRepositoryMock.Delete with params: %#v", *e.params)
+		}
+	}
+
+	afterDeleteCounter := mm_atomic.LoadUint64(&m.afterDeleteCounter)
+	// if default expectation was set then invocations count should be greater than zero
+	if m.DeleteMock.defaultExpectation != nil && afterDeleteCounter < 1 {
+		if m.DeleteMock.defaultExpectation.params == nil {
+			m.t.Error("Expected call to ThingNotificationRepositoryMock.Delete")
+		} else {
+			m.t.Errorf("Expected call to ThingNotificationRepositoryMock.Delete with params: %#v", *m.DeleteMock.defaultExpectation.params)
+		}
+	}
+	// if func was set then invocations count should be greater than zero
+	if m.funcDelete != nil && afterDeleteCounter < 1 {
+		m.t.Error("Expected call to ThingNotificationRepositoryMock.Delete")
+	}
+
+	if !m.DeleteMock.invocationsDone() && afterDeleteCounter > 0 {
+		m.t.Errorf("Expected %d calls to ThingNotificationRepositoryMock.Delete but found %d calls",
+			mm_atomic.LoadUint64(&m.DeleteMock.expectedInvocations), afterDeleteCounter)
+	}
+}
+
+// MinimockFinish checks that all mocked methods have been called the expected number of times
+func (m *ThingNotificationRepositoryMock) MinimockFinish() {
+	m.finishOnce.Do(func() {
+		if !m.minimockDone() {
+			m.MinimockDeleteInspect()
+		}
+	})
+}
+
+// MinimockWait waits for all mocked methods to be called the expected number of times
+func (m *ThingNotificationRepositoryMock) MinimockWait(timeout mm_time.Duration) {
+	timeoutCh := mm_time.After(timeout)
+	for {
+		if m.minimockDone() {
+			return
+		}
+		select {
+		case <-timeoutCh:
+			m.MinimockFinish()
+			return
+		case <-mm_time.After(10 * mm_time.Millisecond):
+		}
+	}
+}
+
+func (m *ThingNotificationRepositoryMock) minimockDone() bool {
+	done := true
+	return done &&
+		m.MinimockDeleteDone()
+}

File diff ditekan karena terlalu besar
+ 525 - 84
internal/api/v1/thing/mocks/thing_repository_minimock.go


+ 756 - 0
internal/api/v1/thing/mocks/thing_tag_repository_minimock.go

@@ -0,0 +1,756 @@
+// Code generated by http://github.com/gojuno/minimock (v3.3.13). DO NOT EDIT.
+
+package mocks
+
+//go:generate minimock -i git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/thing.ThingTagRepository -o thing_tag_repository_minimock.go -n ThingTagRepositoryMock -p mocks
+
+import (
+	"context"
+	"database/sql"
+	"sync"
+	mm_atomic "sync/atomic"
+	mm_time "time"
+
+	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
+	"github.com/gojuno/minimock/v3"
+)
+
+// ThingTagRepositoryMock implements thing.ThingTagRepository
+type ThingTagRepositoryMock struct {
+	t          minimock.Tester
+	finishOnce sync.Once
+
+	funcDeleteByThingID          func(ctx context.Context, thingID int, tx *sql.Tx) (err error)
+	inspectFuncDeleteByThingID   func(ctx context.Context, thingID int, tx *sql.Tx)
+	afterDeleteByThingIDCounter  uint64
+	beforeDeleteByThingIDCounter uint64
+	DeleteByThingIDMock          mThingTagRepositoryMockDeleteByThingID
+
+	funcGetByPlaceID          func(ctx context.Context, placeID int) (ta1 []models.ThingTag, err error)
+	inspectFuncGetByPlaceID   func(ctx context.Context, placeID int)
+	afterGetByPlaceIDCounter  uint64
+	beforeGetByPlaceIDCounter uint64
+	GetByPlaceIDMock          mThingTagRepositoryMockGetByPlaceID
+}
+
+// NewThingTagRepositoryMock returns a mock for thing.ThingTagRepository
+func NewThingTagRepositoryMock(t minimock.Tester) *ThingTagRepositoryMock {
+	m := &ThingTagRepositoryMock{t: t}
+
+	if controller, ok := t.(minimock.MockController); ok {
+		controller.RegisterMocker(m)
+	}
+
+	m.DeleteByThingIDMock = mThingTagRepositoryMockDeleteByThingID{mock: m}
+	m.DeleteByThingIDMock.callArgs = []*ThingTagRepositoryMockDeleteByThingIDParams{}
+
+	m.GetByPlaceIDMock = mThingTagRepositoryMockGetByPlaceID{mock: m}
+	m.GetByPlaceIDMock.callArgs = []*ThingTagRepositoryMockGetByPlaceIDParams{}
+
+	t.Cleanup(m.MinimockFinish)
+
+	return m
+}
+
+type mThingTagRepositoryMockDeleteByThingID struct {
+	optional           bool
+	mock               *ThingTagRepositoryMock
+	defaultExpectation *ThingTagRepositoryMockDeleteByThingIDExpectation
+	expectations       []*ThingTagRepositoryMockDeleteByThingIDExpectation
+
+	callArgs []*ThingTagRepositoryMockDeleteByThingIDParams
+	mutex    sync.RWMutex
+
+	expectedInvocations uint64
+}
+
+// ThingTagRepositoryMockDeleteByThingIDExpectation specifies expectation struct of the ThingTagRepository.DeleteByThingID
+type ThingTagRepositoryMockDeleteByThingIDExpectation struct {
+	mock      *ThingTagRepositoryMock
+	params    *ThingTagRepositoryMockDeleteByThingIDParams
+	paramPtrs *ThingTagRepositoryMockDeleteByThingIDParamPtrs
+	results   *ThingTagRepositoryMockDeleteByThingIDResults
+	Counter   uint64
+}
+
+// ThingTagRepositoryMockDeleteByThingIDParams contains parameters of the ThingTagRepository.DeleteByThingID
+type ThingTagRepositoryMockDeleteByThingIDParams struct {
+	ctx     context.Context
+	thingID int
+	tx      *sql.Tx
+}
+
+// ThingTagRepositoryMockDeleteByThingIDParamPtrs contains pointers to parameters of the ThingTagRepository.DeleteByThingID
+type ThingTagRepositoryMockDeleteByThingIDParamPtrs struct {
+	ctx     *context.Context
+	thingID *int
+	tx      **sql.Tx
+}
+
+// ThingTagRepositoryMockDeleteByThingIDResults contains results of the ThingTagRepository.DeleteByThingID
+type ThingTagRepositoryMockDeleteByThingIDResults struct {
+	err error
+}
+
+// Marks this method to be optional. The default behavior of any method with Return() is '1 or more', meaning
+// the test will fail minimock's automatic final call check if the mocked method was not called at least once.
+// Optional() makes method check to work in '0 or more' mode.
+// It is NOT RECOMMENDED to use this option unless you really need it, as default behaviour helps to
+// catch the problems when the expected method call is totally skipped during test run.
+func (mmDeleteByThingID *mThingTagRepositoryMockDeleteByThingID) Optional() *mThingTagRepositoryMockDeleteByThingID {
+	mmDeleteByThingID.optional = true
+	return mmDeleteByThingID
+}
+
+// Expect sets up expected params for ThingTagRepository.DeleteByThingID
+func (mmDeleteByThingID *mThingTagRepositoryMockDeleteByThingID) Expect(ctx context.Context, thingID int, tx *sql.Tx) *mThingTagRepositoryMockDeleteByThingID {
+	if mmDeleteByThingID.mock.funcDeleteByThingID != nil {
+		mmDeleteByThingID.mock.t.Fatalf("ThingTagRepositoryMock.DeleteByThingID mock is already set by Set")
+	}
+
+	if mmDeleteByThingID.defaultExpectation == nil {
+		mmDeleteByThingID.defaultExpectation = &ThingTagRepositoryMockDeleteByThingIDExpectation{}
+	}
+
+	if mmDeleteByThingID.defaultExpectation.paramPtrs != nil {
+		mmDeleteByThingID.mock.t.Fatalf("ThingTagRepositoryMock.DeleteByThingID mock is already set by ExpectParams functions")
+	}
+
+	mmDeleteByThingID.defaultExpectation.params = &ThingTagRepositoryMockDeleteByThingIDParams{ctx, thingID, tx}
+	for _, e := range mmDeleteByThingID.expectations {
+		if minimock.Equal(e.params, mmDeleteByThingID.defaultExpectation.params) {
+			mmDeleteByThingID.mock.t.Fatalf("Expectation set by When has same params: %#v", *mmDeleteByThingID.defaultExpectation.params)
+		}
+	}
+
+	return mmDeleteByThingID
+}
+
+// ExpectCtxParam1 sets up expected param ctx for ThingTagRepository.DeleteByThingID
+func (mmDeleteByThingID *mThingTagRepositoryMockDeleteByThingID) ExpectCtxParam1(ctx context.Context) *mThingTagRepositoryMockDeleteByThingID {
+	if mmDeleteByThingID.mock.funcDeleteByThingID != nil {
+		mmDeleteByThingID.mock.t.Fatalf("ThingTagRepositoryMock.DeleteByThingID mock is already set by Set")
+	}
+
+	if mmDeleteByThingID.defaultExpectation == nil {
+		mmDeleteByThingID.defaultExpectation = &ThingTagRepositoryMockDeleteByThingIDExpectation{}
+	}
+
+	if mmDeleteByThingID.defaultExpectation.params != nil {
+		mmDeleteByThingID.mock.t.Fatalf("ThingTagRepositoryMock.DeleteByThingID mock is already set by Expect")
+	}
+
+	if mmDeleteByThingID.defaultExpectation.paramPtrs == nil {
+		mmDeleteByThingID.defaultExpectation.paramPtrs = &ThingTagRepositoryMockDeleteByThingIDParamPtrs{}
+	}
+	mmDeleteByThingID.defaultExpectation.paramPtrs.ctx = &ctx
+
+	return mmDeleteByThingID
+}
+
+// ExpectThingIDParam2 sets up expected param thingID for ThingTagRepository.DeleteByThingID
+func (mmDeleteByThingID *mThingTagRepositoryMockDeleteByThingID) ExpectThingIDParam2(thingID int) *mThingTagRepositoryMockDeleteByThingID {
+	if mmDeleteByThingID.mock.funcDeleteByThingID != nil {
+		mmDeleteByThingID.mock.t.Fatalf("ThingTagRepositoryMock.DeleteByThingID mock is already set by Set")
+	}
+
+	if mmDeleteByThingID.defaultExpectation == nil {
+		mmDeleteByThingID.defaultExpectation = &ThingTagRepositoryMockDeleteByThingIDExpectation{}
+	}
+
+	if mmDeleteByThingID.defaultExpectation.params != nil {
+		mmDeleteByThingID.mock.t.Fatalf("ThingTagRepositoryMock.DeleteByThingID mock is already set by Expect")
+	}
+
+	if mmDeleteByThingID.defaultExpectation.paramPtrs == nil {
+		mmDeleteByThingID.defaultExpectation.paramPtrs = &ThingTagRepositoryMockDeleteByThingIDParamPtrs{}
+	}
+	mmDeleteByThingID.defaultExpectation.paramPtrs.thingID = &thingID
+
+	return mmDeleteByThingID
+}
+
+// ExpectTxParam3 sets up expected param tx for ThingTagRepository.DeleteByThingID
+func (mmDeleteByThingID *mThingTagRepositoryMockDeleteByThingID) ExpectTxParam3(tx *sql.Tx) *mThingTagRepositoryMockDeleteByThingID {
+	if mmDeleteByThingID.mock.funcDeleteByThingID != nil {
+		mmDeleteByThingID.mock.t.Fatalf("ThingTagRepositoryMock.DeleteByThingID mock is already set by Set")
+	}
+
+	if mmDeleteByThingID.defaultExpectation == nil {
+		mmDeleteByThingID.defaultExpectation = &ThingTagRepositoryMockDeleteByThingIDExpectation{}
+	}
+
+	if mmDeleteByThingID.defaultExpectation.params != nil {
+		mmDeleteByThingID.mock.t.Fatalf("ThingTagRepositoryMock.DeleteByThingID mock is already set by Expect")
+	}
+
+	if mmDeleteByThingID.defaultExpectation.paramPtrs == nil {
+		mmDeleteByThingID.defaultExpectation.paramPtrs = &ThingTagRepositoryMockDeleteByThingIDParamPtrs{}
+	}
+	mmDeleteByThingID.defaultExpectation.paramPtrs.tx = &tx
+
+	return mmDeleteByThingID
+}
+
+// Inspect accepts an inspector function that has same arguments as the ThingTagRepository.DeleteByThingID
+func (mmDeleteByThingID *mThingTagRepositoryMockDeleteByThingID) Inspect(f func(ctx context.Context, thingID int, tx *sql.Tx)) *mThingTagRepositoryMockDeleteByThingID {
+	if mmDeleteByThingID.mock.inspectFuncDeleteByThingID != nil {
+		mmDeleteByThingID.mock.t.Fatalf("Inspect function is already set for ThingTagRepositoryMock.DeleteByThingID")
+	}
+
+	mmDeleteByThingID.mock.inspectFuncDeleteByThingID = f
+
+	return mmDeleteByThingID
+}
+
+// Return sets up results that will be returned by ThingTagRepository.DeleteByThingID
+func (mmDeleteByThingID *mThingTagRepositoryMockDeleteByThingID) Return(err error) *ThingTagRepositoryMock {
+	if mmDeleteByThingID.mock.funcDeleteByThingID != nil {
+		mmDeleteByThingID.mock.t.Fatalf("ThingTagRepositoryMock.DeleteByThingID mock is already set by Set")
+	}
+
+	if mmDeleteByThingID.defaultExpectation == nil {
+		mmDeleteByThingID.defaultExpectation = &ThingTagRepositoryMockDeleteByThingIDExpectation{mock: mmDeleteByThingID.mock}
+	}
+	mmDeleteByThingID.defaultExpectation.results = &ThingTagRepositoryMockDeleteByThingIDResults{err}
+	return mmDeleteByThingID.mock
+}
+
+// Set uses given function f to mock the ThingTagRepository.DeleteByThingID method
+func (mmDeleteByThingID *mThingTagRepositoryMockDeleteByThingID) Set(f func(ctx context.Context, thingID int, tx *sql.Tx) (err error)) *ThingTagRepositoryMock {
+	if mmDeleteByThingID.defaultExpectation != nil {
+		mmDeleteByThingID.mock.t.Fatalf("Default expectation is already set for the ThingTagRepository.DeleteByThingID method")
+	}
+
+	if len(mmDeleteByThingID.expectations) > 0 {
+		mmDeleteByThingID.mock.t.Fatalf("Some expectations are already set for the ThingTagRepository.DeleteByThingID method")
+	}
+
+	mmDeleteByThingID.mock.funcDeleteByThingID = f
+	return mmDeleteByThingID.mock
+}
+
+// When sets expectation for the ThingTagRepository.DeleteByThingID which will trigger the result defined by the following
+// Then helper
+func (mmDeleteByThingID *mThingTagRepositoryMockDeleteByThingID) When(ctx context.Context, thingID int, tx *sql.Tx) *ThingTagRepositoryMockDeleteByThingIDExpectation {
+	if mmDeleteByThingID.mock.funcDeleteByThingID != nil {
+		mmDeleteByThingID.mock.t.Fatalf("ThingTagRepositoryMock.DeleteByThingID mock is already set by Set")
+	}
+
+	expectation := &ThingTagRepositoryMockDeleteByThingIDExpectation{
+		mock:   mmDeleteByThingID.mock,
+		params: &ThingTagRepositoryMockDeleteByThingIDParams{ctx, thingID, tx},
+	}
+	mmDeleteByThingID.expectations = append(mmDeleteByThingID.expectations, expectation)
+	return expectation
+}
+
+// Then sets up ThingTagRepository.DeleteByThingID return parameters for the expectation previously defined by the When method
+func (e *ThingTagRepositoryMockDeleteByThingIDExpectation) Then(err error) *ThingTagRepositoryMock {
+	e.results = &ThingTagRepositoryMockDeleteByThingIDResults{err}
+	return e.mock
+}
+
+// Times sets number of times ThingTagRepository.DeleteByThingID should be invoked
+func (mmDeleteByThingID *mThingTagRepositoryMockDeleteByThingID) Times(n uint64) *mThingTagRepositoryMockDeleteByThingID {
+	if n == 0 {
+		mmDeleteByThingID.mock.t.Fatalf("Times of ThingTagRepositoryMock.DeleteByThingID mock can not be zero")
+	}
+	mm_atomic.StoreUint64(&mmDeleteByThingID.expectedInvocations, n)
+	return mmDeleteByThingID
+}
+
+func (mmDeleteByThingID *mThingTagRepositoryMockDeleteByThingID) invocationsDone() bool {
+	if len(mmDeleteByThingID.expectations) == 0 && mmDeleteByThingID.defaultExpectation == nil && mmDeleteByThingID.mock.funcDeleteByThingID == nil {
+		return true
+	}
+
+	totalInvocations := mm_atomic.LoadUint64(&mmDeleteByThingID.mock.afterDeleteByThingIDCounter)
+	expectedInvocations := mm_atomic.LoadUint64(&mmDeleteByThingID.expectedInvocations)
+
+	return totalInvocations > 0 && (expectedInvocations == 0 || expectedInvocations == totalInvocations)
+}
+
+// DeleteByThingID implements thing.ThingTagRepository
+func (mmDeleteByThingID *ThingTagRepositoryMock) DeleteByThingID(ctx context.Context, thingID int, tx *sql.Tx) (err error) {
+	mm_atomic.AddUint64(&mmDeleteByThingID.beforeDeleteByThingIDCounter, 1)
+	defer mm_atomic.AddUint64(&mmDeleteByThingID.afterDeleteByThingIDCounter, 1)
+
+	if mmDeleteByThingID.inspectFuncDeleteByThingID != nil {
+		mmDeleteByThingID.inspectFuncDeleteByThingID(ctx, thingID, tx)
+	}
+
+	mm_params := ThingTagRepositoryMockDeleteByThingIDParams{ctx, thingID, tx}
+
+	// Record call args
+	mmDeleteByThingID.DeleteByThingIDMock.mutex.Lock()
+	mmDeleteByThingID.DeleteByThingIDMock.callArgs = append(mmDeleteByThingID.DeleteByThingIDMock.callArgs, &mm_params)
+	mmDeleteByThingID.DeleteByThingIDMock.mutex.Unlock()
+
+	for _, e := range mmDeleteByThingID.DeleteByThingIDMock.expectations {
+		if minimock.Equal(*e.params, mm_params) {
+			mm_atomic.AddUint64(&e.Counter, 1)
+			return e.results.err
+		}
+	}
+
+	if mmDeleteByThingID.DeleteByThingIDMock.defaultExpectation != nil {
+		mm_atomic.AddUint64(&mmDeleteByThingID.DeleteByThingIDMock.defaultExpectation.Counter, 1)
+		mm_want := mmDeleteByThingID.DeleteByThingIDMock.defaultExpectation.params
+		mm_want_ptrs := mmDeleteByThingID.DeleteByThingIDMock.defaultExpectation.paramPtrs
+
+		mm_got := ThingTagRepositoryMockDeleteByThingIDParams{ctx, thingID, tx}
+
+		if mm_want_ptrs != nil {
+
+			if mm_want_ptrs.ctx != nil && !minimock.Equal(*mm_want_ptrs.ctx, mm_got.ctx) {
+				mmDeleteByThingID.t.Errorf("ThingTagRepositoryMock.DeleteByThingID got unexpected parameter ctx, want: %#v, got: %#v%s\n", *mm_want_ptrs.ctx, mm_got.ctx, minimock.Diff(*mm_want_ptrs.ctx, mm_got.ctx))
+			}
+
+			if mm_want_ptrs.thingID != nil && !minimock.Equal(*mm_want_ptrs.thingID, mm_got.thingID) {
+				mmDeleteByThingID.t.Errorf("ThingTagRepositoryMock.DeleteByThingID got unexpected parameter thingID, want: %#v, got: %#v%s\n", *mm_want_ptrs.thingID, mm_got.thingID, minimock.Diff(*mm_want_ptrs.thingID, mm_got.thingID))
+			}
+
+			if mm_want_ptrs.tx != nil && !minimock.Equal(*mm_want_ptrs.tx, mm_got.tx) {
+				mmDeleteByThingID.t.Errorf("ThingTagRepositoryMock.DeleteByThingID got unexpected parameter tx, want: %#v, got: %#v%s\n", *mm_want_ptrs.tx, mm_got.tx, minimock.Diff(*mm_want_ptrs.tx, mm_got.tx))
+			}
+
+		} else if mm_want != nil && !minimock.Equal(*mm_want, mm_got) {
+			mmDeleteByThingID.t.Errorf("ThingTagRepositoryMock.DeleteByThingID got unexpected parameters, want: %#v, got: %#v%s\n", *mm_want, mm_got, minimock.Diff(*mm_want, mm_got))
+		}
+
+		mm_results := mmDeleteByThingID.DeleteByThingIDMock.defaultExpectation.results
+		if mm_results == nil {
+			mmDeleteByThingID.t.Fatal("No results are set for the ThingTagRepositoryMock.DeleteByThingID")
+		}
+		return (*mm_results).err
+	}
+	if mmDeleteByThingID.funcDeleteByThingID != nil {
+		return mmDeleteByThingID.funcDeleteByThingID(ctx, thingID, tx)
+	}
+	mmDeleteByThingID.t.Fatalf("Unexpected call to ThingTagRepositoryMock.DeleteByThingID. %v %v %v", ctx, thingID, tx)
+	return
+}
+
+// DeleteByThingIDAfterCounter returns a count of finished ThingTagRepositoryMock.DeleteByThingID invocations
+func (mmDeleteByThingID *ThingTagRepositoryMock) DeleteByThingIDAfterCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmDeleteByThingID.afterDeleteByThingIDCounter)
+}
+
+// DeleteByThingIDBeforeCounter returns a count of ThingTagRepositoryMock.DeleteByThingID invocations
+func (mmDeleteByThingID *ThingTagRepositoryMock) DeleteByThingIDBeforeCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmDeleteByThingID.beforeDeleteByThingIDCounter)
+}
+
+// Calls returns a list of arguments used in each call to ThingTagRepositoryMock.DeleteByThingID.
+// The list is in the same order as the calls were made (i.e. recent calls have a higher index)
+func (mmDeleteByThingID *mThingTagRepositoryMockDeleteByThingID) Calls() []*ThingTagRepositoryMockDeleteByThingIDParams {
+	mmDeleteByThingID.mutex.RLock()
+
+	argCopy := make([]*ThingTagRepositoryMockDeleteByThingIDParams, len(mmDeleteByThingID.callArgs))
+	copy(argCopy, mmDeleteByThingID.callArgs)
+
+	mmDeleteByThingID.mutex.RUnlock()
+
+	return argCopy
+}
+
+// MinimockDeleteByThingIDDone returns true if the count of the DeleteByThingID invocations corresponds
+// the number of defined expectations
+func (m *ThingTagRepositoryMock) MinimockDeleteByThingIDDone() bool {
+	if m.DeleteByThingIDMock.optional {
+		// Optional methods provide '0 or more' call count restriction.
+		return true
+	}
+
+	for _, e := range m.DeleteByThingIDMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			return false
+		}
+	}
+
+	return m.DeleteByThingIDMock.invocationsDone()
+}
+
+// MinimockDeleteByThingIDInspect logs each unmet expectation
+func (m *ThingTagRepositoryMock) MinimockDeleteByThingIDInspect() {
+	for _, e := range m.DeleteByThingIDMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			m.t.Errorf("Expected call to ThingTagRepositoryMock.DeleteByThingID with params: %#v", *e.params)
+		}
+	}
+
+	afterDeleteByThingIDCounter := mm_atomic.LoadUint64(&m.afterDeleteByThingIDCounter)
+	// if default expectation was set then invocations count should be greater than zero
+	if m.DeleteByThingIDMock.defaultExpectation != nil && afterDeleteByThingIDCounter < 1 {
+		if m.DeleteByThingIDMock.defaultExpectation.params == nil {
+			m.t.Error("Expected call to ThingTagRepositoryMock.DeleteByThingID")
+		} else {
+			m.t.Errorf("Expected call to ThingTagRepositoryMock.DeleteByThingID with params: %#v", *m.DeleteByThingIDMock.defaultExpectation.params)
+		}
+	}
+	// if func was set then invocations count should be greater than zero
+	if m.funcDeleteByThingID != nil && afterDeleteByThingIDCounter < 1 {
+		m.t.Error("Expected call to ThingTagRepositoryMock.DeleteByThingID")
+	}
+
+	if !m.DeleteByThingIDMock.invocationsDone() && afterDeleteByThingIDCounter > 0 {
+		m.t.Errorf("Expected %d calls to ThingTagRepositoryMock.DeleteByThingID but found %d calls",
+			mm_atomic.LoadUint64(&m.DeleteByThingIDMock.expectedInvocations), afterDeleteByThingIDCounter)
+	}
+}
+
+type mThingTagRepositoryMockGetByPlaceID struct {
+	optional           bool
+	mock               *ThingTagRepositoryMock
+	defaultExpectation *ThingTagRepositoryMockGetByPlaceIDExpectation
+	expectations       []*ThingTagRepositoryMockGetByPlaceIDExpectation
+
+	callArgs []*ThingTagRepositoryMockGetByPlaceIDParams
+	mutex    sync.RWMutex
+
+	expectedInvocations uint64
+}
+
+// ThingTagRepositoryMockGetByPlaceIDExpectation specifies expectation struct of the ThingTagRepository.GetByPlaceID
+type ThingTagRepositoryMockGetByPlaceIDExpectation struct {
+	mock      *ThingTagRepositoryMock
+	params    *ThingTagRepositoryMockGetByPlaceIDParams
+	paramPtrs *ThingTagRepositoryMockGetByPlaceIDParamPtrs
+	results   *ThingTagRepositoryMockGetByPlaceIDResults
+	Counter   uint64
+}
+
+// ThingTagRepositoryMockGetByPlaceIDParams contains parameters of the ThingTagRepository.GetByPlaceID
+type ThingTagRepositoryMockGetByPlaceIDParams struct {
+	ctx     context.Context
+	placeID int
+}
+
+// ThingTagRepositoryMockGetByPlaceIDParamPtrs contains pointers to parameters of the ThingTagRepository.GetByPlaceID
+type ThingTagRepositoryMockGetByPlaceIDParamPtrs struct {
+	ctx     *context.Context
+	placeID *int
+}
+
+// ThingTagRepositoryMockGetByPlaceIDResults contains results of the ThingTagRepository.GetByPlaceID
+type ThingTagRepositoryMockGetByPlaceIDResults struct {
+	ta1 []models.ThingTag
+	err error
+}
+
+// Marks this method to be optional. The default behavior of any method with Return() is '1 or more', meaning
+// the test will fail minimock's automatic final call check if the mocked method was not called at least once.
+// Optional() makes method check to work in '0 or more' mode.
+// It is NOT RECOMMENDED to use this option unless you really need it, as default behaviour helps to
+// catch the problems when the expected method call is totally skipped during test run.
+func (mmGetByPlaceID *mThingTagRepositoryMockGetByPlaceID) Optional() *mThingTagRepositoryMockGetByPlaceID {
+	mmGetByPlaceID.optional = true
+	return mmGetByPlaceID
+}
+
+// Expect sets up expected params for ThingTagRepository.GetByPlaceID
+func (mmGetByPlaceID *mThingTagRepositoryMockGetByPlaceID) Expect(ctx context.Context, placeID int) *mThingTagRepositoryMockGetByPlaceID {
+	if mmGetByPlaceID.mock.funcGetByPlaceID != nil {
+		mmGetByPlaceID.mock.t.Fatalf("ThingTagRepositoryMock.GetByPlaceID mock is already set by Set")
+	}
+
+	if mmGetByPlaceID.defaultExpectation == nil {
+		mmGetByPlaceID.defaultExpectation = &ThingTagRepositoryMockGetByPlaceIDExpectation{}
+	}
+
+	if mmGetByPlaceID.defaultExpectation.paramPtrs != nil {
+		mmGetByPlaceID.mock.t.Fatalf("ThingTagRepositoryMock.GetByPlaceID mock is already set by ExpectParams functions")
+	}
+
+	mmGetByPlaceID.defaultExpectation.params = &ThingTagRepositoryMockGetByPlaceIDParams{ctx, placeID}
+	for _, e := range mmGetByPlaceID.expectations {
+		if minimock.Equal(e.params, mmGetByPlaceID.defaultExpectation.params) {
+			mmGetByPlaceID.mock.t.Fatalf("Expectation set by When has same params: %#v", *mmGetByPlaceID.defaultExpectation.params)
+		}
+	}
+
+	return mmGetByPlaceID
+}
+
+// ExpectCtxParam1 sets up expected param ctx for ThingTagRepository.GetByPlaceID
+func (mmGetByPlaceID *mThingTagRepositoryMockGetByPlaceID) ExpectCtxParam1(ctx context.Context) *mThingTagRepositoryMockGetByPlaceID {
+	if mmGetByPlaceID.mock.funcGetByPlaceID != nil {
+		mmGetByPlaceID.mock.t.Fatalf("ThingTagRepositoryMock.GetByPlaceID mock is already set by Set")
+	}
+
+	if mmGetByPlaceID.defaultExpectation == nil {
+		mmGetByPlaceID.defaultExpectation = &ThingTagRepositoryMockGetByPlaceIDExpectation{}
+	}
+
+	if mmGetByPlaceID.defaultExpectation.params != nil {
+		mmGetByPlaceID.mock.t.Fatalf("ThingTagRepositoryMock.GetByPlaceID mock is already set by Expect")
+	}
+
+	if mmGetByPlaceID.defaultExpectation.paramPtrs == nil {
+		mmGetByPlaceID.defaultExpectation.paramPtrs = &ThingTagRepositoryMockGetByPlaceIDParamPtrs{}
+	}
+	mmGetByPlaceID.defaultExpectation.paramPtrs.ctx = &ctx
+
+	return mmGetByPlaceID
+}
+
+// ExpectPlaceIDParam2 sets up expected param placeID for ThingTagRepository.GetByPlaceID
+func (mmGetByPlaceID *mThingTagRepositoryMockGetByPlaceID) ExpectPlaceIDParam2(placeID int) *mThingTagRepositoryMockGetByPlaceID {
+	if mmGetByPlaceID.mock.funcGetByPlaceID != nil {
+		mmGetByPlaceID.mock.t.Fatalf("ThingTagRepositoryMock.GetByPlaceID mock is already set by Set")
+	}
+
+	if mmGetByPlaceID.defaultExpectation == nil {
+		mmGetByPlaceID.defaultExpectation = &ThingTagRepositoryMockGetByPlaceIDExpectation{}
+	}
+
+	if mmGetByPlaceID.defaultExpectation.params != nil {
+		mmGetByPlaceID.mock.t.Fatalf("ThingTagRepositoryMock.GetByPlaceID mock is already set by Expect")
+	}
+
+	if mmGetByPlaceID.defaultExpectation.paramPtrs == nil {
+		mmGetByPlaceID.defaultExpectation.paramPtrs = &ThingTagRepositoryMockGetByPlaceIDParamPtrs{}
+	}
+	mmGetByPlaceID.defaultExpectation.paramPtrs.placeID = &placeID
+
+	return mmGetByPlaceID
+}
+
+// Inspect accepts an inspector function that has same arguments as the ThingTagRepository.GetByPlaceID
+func (mmGetByPlaceID *mThingTagRepositoryMockGetByPlaceID) Inspect(f func(ctx context.Context, placeID int)) *mThingTagRepositoryMockGetByPlaceID {
+	if mmGetByPlaceID.mock.inspectFuncGetByPlaceID != nil {
+		mmGetByPlaceID.mock.t.Fatalf("Inspect function is already set for ThingTagRepositoryMock.GetByPlaceID")
+	}
+
+	mmGetByPlaceID.mock.inspectFuncGetByPlaceID = f
+
+	return mmGetByPlaceID
+}
+
+// Return sets up results that will be returned by ThingTagRepository.GetByPlaceID
+func (mmGetByPlaceID *mThingTagRepositoryMockGetByPlaceID) Return(ta1 []models.ThingTag, err error) *ThingTagRepositoryMock {
+	if mmGetByPlaceID.mock.funcGetByPlaceID != nil {
+		mmGetByPlaceID.mock.t.Fatalf("ThingTagRepositoryMock.GetByPlaceID mock is already set by Set")
+	}
+
+	if mmGetByPlaceID.defaultExpectation == nil {
+		mmGetByPlaceID.defaultExpectation = &ThingTagRepositoryMockGetByPlaceIDExpectation{mock: mmGetByPlaceID.mock}
+	}
+	mmGetByPlaceID.defaultExpectation.results = &ThingTagRepositoryMockGetByPlaceIDResults{ta1, err}
+	return mmGetByPlaceID.mock
+}
+
+// Set uses given function f to mock the ThingTagRepository.GetByPlaceID method
+func (mmGetByPlaceID *mThingTagRepositoryMockGetByPlaceID) Set(f func(ctx context.Context, placeID int) (ta1 []models.ThingTag, err error)) *ThingTagRepositoryMock {
+	if mmGetByPlaceID.defaultExpectation != nil {
+		mmGetByPlaceID.mock.t.Fatalf("Default expectation is already set for the ThingTagRepository.GetByPlaceID method")
+	}
+
+	if len(mmGetByPlaceID.expectations) > 0 {
+		mmGetByPlaceID.mock.t.Fatalf("Some expectations are already set for the ThingTagRepository.GetByPlaceID method")
+	}
+
+	mmGetByPlaceID.mock.funcGetByPlaceID = f
+	return mmGetByPlaceID.mock
+}
+
+// When sets expectation for the ThingTagRepository.GetByPlaceID which will trigger the result defined by the following
+// Then helper
+func (mmGetByPlaceID *mThingTagRepositoryMockGetByPlaceID) When(ctx context.Context, placeID int) *ThingTagRepositoryMockGetByPlaceIDExpectation {
+	if mmGetByPlaceID.mock.funcGetByPlaceID != nil {
+		mmGetByPlaceID.mock.t.Fatalf("ThingTagRepositoryMock.GetByPlaceID mock is already set by Set")
+	}
+
+	expectation := &ThingTagRepositoryMockGetByPlaceIDExpectation{
+		mock:   mmGetByPlaceID.mock,
+		params: &ThingTagRepositoryMockGetByPlaceIDParams{ctx, placeID},
+	}
+	mmGetByPlaceID.expectations = append(mmGetByPlaceID.expectations, expectation)
+	return expectation
+}
+
+// Then sets up ThingTagRepository.GetByPlaceID return parameters for the expectation previously defined by the When method
+func (e *ThingTagRepositoryMockGetByPlaceIDExpectation) Then(ta1 []models.ThingTag, err error) *ThingTagRepositoryMock {
+	e.results = &ThingTagRepositoryMockGetByPlaceIDResults{ta1, err}
+	return e.mock
+}
+
+// Times sets number of times ThingTagRepository.GetByPlaceID should be invoked
+func (mmGetByPlaceID *mThingTagRepositoryMockGetByPlaceID) Times(n uint64) *mThingTagRepositoryMockGetByPlaceID {
+	if n == 0 {
+		mmGetByPlaceID.mock.t.Fatalf("Times of ThingTagRepositoryMock.GetByPlaceID mock can not be zero")
+	}
+	mm_atomic.StoreUint64(&mmGetByPlaceID.expectedInvocations, n)
+	return mmGetByPlaceID
+}
+
+func (mmGetByPlaceID *mThingTagRepositoryMockGetByPlaceID) invocationsDone() bool {
+	if len(mmGetByPlaceID.expectations) == 0 && mmGetByPlaceID.defaultExpectation == nil && mmGetByPlaceID.mock.funcGetByPlaceID == nil {
+		return true
+	}
+
+	totalInvocations := mm_atomic.LoadUint64(&mmGetByPlaceID.mock.afterGetByPlaceIDCounter)
+	expectedInvocations := mm_atomic.LoadUint64(&mmGetByPlaceID.expectedInvocations)
+
+	return totalInvocations > 0 && (expectedInvocations == 0 || expectedInvocations == totalInvocations)
+}
+
+// GetByPlaceID implements thing.ThingTagRepository
+func (mmGetByPlaceID *ThingTagRepositoryMock) GetByPlaceID(ctx context.Context, placeID int) (ta1 []models.ThingTag, err error) {
+	mm_atomic.AddUint64(&mmGetByPlaceID.beforeGetByPlaceIDCounter, 1)
+	defer mm_atomic.AddUint64(&mmGetByPlaceID.afterGetByPlaceIDCounter, 1)
+
+	if mmGetByPlaceID.inspectFuncGetByPlaceID != nil {
+		mmGetByPlaceID.inspectFuncGetByPlaceID(ctx, placeID)
+	}
+
+	mm_params := ThingTagRepositoryMockGetByPlaceIDParams{ctx, placeID}
+
+	// Record call args
+	mmGetByPlaceID.GetByPlaceIDMock.mutex.Lock()
+	mmGetByPlaceID.GetByPlaceIDMock.callArgs = append(mmGetByPlaceID.GetByPlaceIDMock.callArgs, &mm_params)
+	mmGetByPlaceID.GetByPlaceIDMock.mutex.Unlock()
+
+	for _, e := range mmGetByPlaceID.GetByPlaceIDMock.expectations {
+		if minimock.Equal(*e.params, mm_params) {
+			mm_atomic.AddUint64(&e.Counter, 1)
+			return e.results.ta1, e.results.err
+		}
+	}
+
+	if mmGetByPlaceID.GetByPlaceIDMock.defaultExpectation != nil {
+		mm_atomic.AddUint64(&mmGetByPlaceID.GetByPlaceIDMock.defaultExpectation.Counter, 1)
+		mm_want := mmGetByPlaceID.GetByPlaceIDMock.defaultExpectation.params
+		mm_want_ptrs := mmGetByPlaceID.GetByPlaceIDMock.defaultExpectation.paramPtrs
+
+		mm_got := ThingTagRepositoryMockGetByPlaceIDParams{ctx, placeID}
+
+		if mm_want_ptrs != nil {
+
+			if mm_want_ptrs.ctx != nil && !minimock.Equal(*mm_want_ptrs.ctx, mm_got.ctx) {
+				mmGetByPlaceID.t.Errorf("ThingTagRepositoryMock.GetByPlaceID got unexpected parameter ctx, want: %#v, got: %#v%s\n", *mm_want_ptrs.ctx, mm_got.ctx, minimock.Diff(*mm_want_ptrs.ctx, mm_got.ctx))
+			}
+
+			if mm_want_ptrs.placeID != nil && !minimock.Equal(*mm_want_ptrs.placeID, mm_got.placeID) {
+				mmGetByPlaceID.t.Errorf("ThingTagRepositoryMock.GetByPlaceID got unexpected parameter placeID, want: %#v, got: %#v%s\n", *mm_want_ptrs.placeID, mm_got.placeID, minimock.Diff(*mm_want_ptrs.placeID, mm_got.placeID))
+			}
+
+		} else if mm_want != nil && !minimock.Equal(*mm_want, mm_got) {
+			mmGetByPlaceID.t.Errorf("ThingTagRepositoryMock.GetByPlaceID got unexpected parameters, want: %#v, got: %#v%s\n", *mm_want, mm_got, minimock.Diff(*mm_want, mm_got))
+		}
+
+		mm_results := mmGetByPlaceID.GetByPlaceIDMock.defaultExpectation.results
+		if mm_results == nil {
+			mmGetByPlaceID.t.Fatal("No results are set for the ThingTagRepositoryMock.GetByPlaceID")
+		}
+		return (*mm_results).ta1, (*mm_results).err
+	}
+	if mmGetByPlaceID.funcGetByPlaceID != nil {
+		return mmGetByPlaceID.funcGetByPlaceID(ctx, placeID)
+	}
+	mmGetByPlaceID.t.Fatalf("Unexpected call to ThingTagRepositoryMock.GetByPlaceID. %v %v", ctx, placeID)
+	return
+}
+
+// GetByPlaceIDAfterCounter returns a count of finished ThingTagRepositoryMock.GetByPlaceID invocations
+func (mmGetByPlaceID *ThingTagRepositoryMock) GetByPlaceIDAfterCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmGetByPlaceID.afterGetByPlaceIDCounter)
+}
+
+// GetByPlaceIDBeforeCounter returns a count of ThingTagRepositoryMock.GetByPlaceID invocations
+func (mmGetByPlaceID *ThingTagRepositoryMock) GetByPlaceIDBeforeCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmGetByPlaceID.beforeGetByPlaceIDCounter)
+}
+
+// Calls returns a list of arguments used in each call to ThingTagRepositoryMock.GetByPlaceID.
+// The list is in the same order as the calls were made (i.e. recent calls have a higher index)
+func (mmGetByPlaceID *mThingTagRepositoryMockGetByPlaceID) Calls() []*ThingTagRepositoryMockGetByPlaceIDParams {
+	mmGetByPlaceID.mutex.RLock()
+
+	argCopy := make([]*ThingTagRepositoryMockGetByPlaceIDParams, len(mmGetByPlaceID.callArgs))
+	copy(argCopy, mmGetByPlaceID.callArgs)
+
+	mmGetByPlaceID.mutex.RUnlock()
+
+	return argCopy
+}
+
+// MinimockGetByPlaceIDDone returns true if the count of the GetByPlaceID invocations corresponds
+// the number of defined expectations
+func (m *ThingTagRepositoryMock) MinimockGetByPlaceIDDone() bool {
+	if m.GetByPlaceIDMock.optional {
+		// Optional methods provide '0 or more' call count restriction.
+		return true
+	}
+
+	for _, e := range m.GetByPlaceIDMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			return false
+		}
+	}
+
+	return m.GetByPlaceIDMock.invocationsDone()
+}
+
+// MinimockGetByPlaceIDInspect logs each unmet expectation
+func (m *ThingTagRepositoryMock) MinimockGetByPlaceIDInspect() {
+	for _, e := range m.GetByPlaceIDMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			m.t.Errorf("Expected call to ThingTagRepositoryMock.GetByPlaceID with params: %#v", *e.params)
+		}
+	}
+
+	afterGetByPlaceIDCounter := mm_atomic.LoadUint64(&m.afterGetByPlaceIDCounter)
+	// if default expectation was set then invocations count should be greater than zero
+	if m.GetByPlaceIDMock.defaultExpectation != nil && afterGetByPlaceIDCounter < 1 {
+		if m.GetByPlaceIDMock.defaultExpectation.params == nil {
+			m.t.Error("Expected call to ThingTagRepositoryMock.GetByPlaceID")
+		} else {
+			m.t.Errorf("Expected call to ThingTagRepositoryMock.GetByPlaceID with params: %#v", *m.GetByPlaceIDMock.defaultExpectation.params)
+		}
+	}
+	// if func was set then invocations count should be greater than zero
+	if m.funcGetByPlaceID != nil && afterGetByPlaceIDCounter < 1 {
+		m.t.Error("Expected call to ThingTagRepositoryMock.GetByPlaceID")
+	}
+
+	if !m.GetByPlaceIDMock.invocationsDone() && afterGetByPlaceIDCounter > 0 {
+		m.t.Errorf("Expected %d calls to ThingTagRepositoryMock.GetByPlaceID but found %d calls",
+			mm_atomic.LoadUint64(&m.GetByPlaceIDMock.expectedInvocations), afterGetByPlaceIDCounter)
+	}
+}
+
+// MinimockFinish checks that all mocked methods have been called the expected number of times
+func (m *ThingTagRepositoryMock) MinimockFinish() {
+	m.finishOnce.Do(func() {
+		if !m.minimockDone() {
+			m.MinimockDeleteByThingIDInspect()
+
+			m.MinimockGetByPlaceIDInspect()
+		}
+	})
+}
+
+// MinimockWait waits for all mocked methods to be called the expected number of times
+func (m *ThingTagRepositoryMock) MinimockWait(timeout mm_time.Duration) {
+	timeoutCh := mm_time.After(timeout)
+	for {
+		if m.minimockDone() {
+			return
+		}
+		select {
+		case <-timeoutCh:
+			m.MinimockFinish()
+			return
+		case <-mm_time.After(10 * mm_time.Millisecond):
+		}
+	}
+}
+
+func (m *ThingTagRepositoryMock) minimockDone() bool {
+	done := true
+	return done &&
+		m.MinimockDeleteByThingIDDone() &&
+		m.MinimockGetByPlaceIDDone()
+}

+ 5 - 5
internal/api/v1/thing/search_thing.go

@@ -5,10 +5,10 @@ import (
 	"regexp"
 	"strings"
 
+	"github.com/gofiber/fiber/v2"
+
 	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/mappers"
-	"github.com/gofiber/fiber/v2"
 )
 
 // @Router 		/api/v1/things/search/{search} [get]
@@ -21,7 +21,7 @@ import (
 // @security 	APIKey
 // @Accept      json
 // @Produce     json
-func SearchThingHandler(sp interfaces.ServiceProvider) fiber.Handler {
+func SearchThingHandler(thingRepository ThingRepository) fiber.Handler {
 	return func(fctx *fiber.Ctx) error {
 		ctx := fctx.Context()
 		search, _ := url.QueryUnescape(fctx.Params("search", ""))
@@ -34,13 +34,13 @@ func SearchThingHandler(sp interfaces.ServiceProvider) fiber.Handler {
 			return fiber.NewError(fiber.StatusBadRequest, "")
 		}
 
-		res, err := sp.GetThingRepository().Search(ctx, search)
+		res, err := thingRepository.Search(ctx, search)
 		if err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
 		res = helpers.ApplyLocation(fctx, res)
 
-		return fctx.JSON(mappers.ConvertToThingsResponseDTO(res))
+		return fctx.JSON(mappers.ToThingsResponse(res))
 	}
 }

+ 22 - 22
internal/api/v1/thing/search_thing_test.go

@@ -7,28 +7,27 @@ import (
 	"net/url"
 	"testing"
 
-	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
-	repoMocks "git.dmitriygnatenko.ru/dima/homethings/internal/repositories/mocks"
-	sp "git.dmitriygnatenko.ru/dima/homethings/internal/service_provider"
 	"github.com/brianvoe/gofakeit/v6"
 	"github.com/gofiber/fiber/v2"
 	"github.com/gojuno/minimock/v3"
 	"github.com/stretchr/testify/assert"
+
+	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/thing/mocks"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
 )
 
-func Test_SearchThingHandler(t *testing.T) {
+func TestSearchThingHandler(t *testing.T) {
+	t.Parallel()
+
 	type req struct {
 		method string
 		route  string
 	}
 
 	var (
-		mc = minimock.NewController(t)
-
 		search    = gofakeit.LetterN(10)
 		testError = errors.New(gofakeit.Phrase())
 		layout    = "2006-01-02 15:04:05"
@@ -84,7 +83,7 @@ func Test_SearchThingHandler(t *testing.T) {
 		req           req
 		resCode       int
 		resBody       interface{}
-		thingRepoMock func(mc *minimock.Controller) interfaces.ThingRepository
+		thingRepoMock func(mc *minimock.Controller) ThingRepository
 	}{
 		{
 			name: "negative case - bad request",
@@ -93,8 +92,8 @@ func Test_SearchThingHandler(t *testing.T) {
 				route:  "/v1/things/search/" + url.QueryEscape(gofakeit.LetterN(2)),
 			},
 			resCode: fiber.StatusBadRequest,
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				return repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				return mocks.NewThingRepositoryMock(mc)
 			},
 		},
 		{
@@ -104,16 +103,16 @@ func Test_SearchThingHandler(t *testing.T) {
 				route:  "/v1/things/search/" + url.QueryEscape(gofakeit.LetterN(10)+":"),
 			},
 			resCode: fiber.StatusBadRequest,
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				return repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				return mocks.NewThingRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - repository error",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				mock := repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				mock := mocks.NewThingRepositoryMock(mc)
 
 				mock.SearchMock.Inspect(func(ctx context.Context, s string) {
 					assert.Equal(mc, search, s)
@@ -127,8 +126,8 @@ func Test_SearchThingHandler(t *testing.T) {
 			req:     correctReq,
 			resCode: fiber.StatusOK,
 			resBody: expectedRes,
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				mock := repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				mock := mocks.NewThingRepositoryMock(mc)
 
 				mock.SearchMock.Inspect(func(ctx context.Context, s string) {
 					assert.Equal(mc, search, s)
@@ -141,10 +140,11 @@ func Test_SearchThingHandler(t *testing.T) {
 
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			fiberApp := fiber.New()
-			serviceProvider := sp.InitMock(tt.thingRepoMock(mc))
+			t.Parallel()
 
-			fiberApp.Get("/v1/things/search/:search", SearchThingHandler(serviceProvider))
+			mc := minimock.NewController(t)
+			fiberApp := fiber.New()
+			fiberApp.Get("/v1/things/search/:search", SearchThingHandler(tt.thingRepoMock(mc)))
 
 			fiberRes, _ := fiberApp.Test(httptest.NewRequest(tt.req.method, tt.req.route, nil), API.DefaultTestTimeOut)
 			assert.Equal(t, tt.resCode, fiberRes.StatusCode)

+ 15 - 12
internal/api/v1/thing/update_thing.go

@@ -1,14 +1,14 @@
 package thing
 
 import (
+	"github.com/go-playground/validator/v10"
+	"github.com/gofiber/fiber/v2"
+
 	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/factory"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
 	"git.dmitriygnatenko.ru/dima/homethings/internal/mappers"
-	"github.com/go-playground/validator/v10"
-	"github.com/gofiber/fiber/v2"
 )
 
 // @Router 		/api/v1/things/{thingId} [put]
@@ -22,7 +22,10 @@ import (
 // @security 	APIKey
 // @Accept      json
 // @Produce     json
-func UpdateThingHandler(sp interfaces.ServiceProvider) fiber.Handler {
+func UpdateThingHandler(
+	thingRepository ThingRepository,
+	placeThingRepository PlaceThingRepository,
+) fiber.Handler {
 	return func(fctx *fiber.Ctx) error {
 		ctx := fctx.Context()
 		id, err := fctx.ParamsInt("thingId")
@@ -40,46 +43,46 @@ func UpdateThingHandler(sp interfaces.ServiceProvider) fiber.Handler {
 			return fctx.Status(fiber.StatusBadRequest).JSON(factory.CreateValidateErrorResponse(err))
 		}
 
-		thing, err := sp.GetThingRepository().Get(ctx, id)
+		thing, err := thingRepository.Get(ctx, id)
 		if err != nil {
 			return fiber.NewError(fiber.StatusBadRequest, err.Error())
 		}
 
-		placeThing, err := sp.GetPlaceThingRepository().GetByThingID(ctx, id)
+		placeThing, err := placeThingRepository.GetByThingID(ctx, id)
 		if err != nil {
 			return fiber.NewError(fiber.StatusBadRequest, err.Error())
 		}
 
-		tx, err := sp.GetThingRepository().BeginTx(ctx, API.DefaultTxLevel)
+		tx, err := thingRepository.BeginTx(ctx, API.DefaultTxLevel)
 		if err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
 		if req.Title != thing.Title || req.Description != thing.Description {
-			err = sp.GetThingRepository().Update(ctx, mappers.ConvertToUpdateThingRequestModel(id, req), tx)
+			err = thingRepository.Update(ctx, mappers.ToUpdateThingRequest(id, req), tx)
 			if err != nil {
 				return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 			}
 		}
 
 		if placeThing.PlaceID != req.PlaceID {
-			err = sp.GetPlaceThingRepository().UpdatePlace(ctx, mappers.ConvertToUpdatePlaceThingRequestModel(id, req.PlaceID), tx)
+			err = placeThingRepository.UpdatePlace(ctx, mappers.ToUpdatePlaceThingRequest(id, req.PlaceID), tx)
 			if err != nil {
 				return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 			}
 		}
 
-		if err = sp.GetThingRepository().CommitTx(tx); err != nil {
+		if err = thingRepository.CommitTx(tx); err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
-		res, err := sp.GetThingRepository().Get(ctx, id)
+		res, err := thingRepository.Get(ctx, id)
 		if err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
 		res = helpers.ApplyLocation(fctx, res)
 
-		return fctx.JSON(mappers.ConvertToThingResponseDTO(*res))
+		return fctx.JSON(mappers.ToThingResponse(*res))
 	}
 }

+ 63 - 62
internal/api/v1/thing/update_thing_test.go

@@ -8,20 +8,21 @@ import (
 	"strconv"
 	"testing"
 
-	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
-	repoMocks "git.dmitriygnatenko.ru/dima/homethings/internal/repositories/mocks"
-	sp "git.dmitriygnatenko.ru/dima/homethings/internal/service_provider"
 	"github.com/brianvoe/gofakeit/v6"
 	"github.com/gofiber/fiber/v2"
 	"github.com/gojuno/minimock/v3"
 	"github.com/stretchr/testify/assert"
+
+	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/thing/mocks"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
 )
 
-func Test_UpdateThingHandler(t *testing.T) {
+func TestUpdateThingHandler(t *testing.T) {
+	t.Parallel()
+
 	type req struct {
 		method      string
 		route       string
@@ -30,7 +31,6 @@ func Test_UpdateThingHandler(t *testing.T) {
 	}
 
 	var (
-		mc          = minimock.NewController(t)
 		placeID     = gofakeit.Number(1, 1000)
 		thingID     = gofakeit.Number(1, 1000)
 		title       = gofakeit.Phrase()
@@ -85,16 +85,16 @@ func Test_UpdateThingHandler(t *testing.T) {
 		req                req
 		resCode            int
 		resBody            interface{}
-		thingRepoMock      func(mc *minimock.Controller) interfaces.ThingRepository
-		placeThingRepoMock func(mc *minimock.Controller) interfaces.PlaceThingRepository
+		thingRepoMock      func(mc *minimock.Controller) ThingRepository
+		placeThingRepoMock func(mc *minimock.Controller) PlaceThingRepository
 	}{
 		{
 			name:    "positive case",
 			req:     correctReq,
 			resCode: fiber.StatusOK,
 			resBody: expectedRes,
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				mock := repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				mock := mocks.NewThingRepositoryMock(mc)
 
 				mock.BeginTxMock.Return(nil, nil)
 
@@ -115,8 +115,8 @@ func Test_UpdateThingHandler(t *testing.T) {
 
 				return mock
 			},
-			placeThingRepoMock: func(mc *minimock.Controller) interfaces.PlaceThingRepository {
-				mock := repoMocks.NewPlaceThingRepositoryMock(mc)
+			placeThingRepoMock: func(mc *minimock.Controller) PlaceThingRepository {
+				mock := mocks.NewPlaceThingRepositoryMock(mc)
 
 				mock.GetByThingIDMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -137,11 +137,11 @@ func Test_UpdateThingHandler(t *testing.T) {
 				route:  "/v1/things/" + gofakeit.Word(),
 			},
 			resCode: fiber.StatusBadRequest,
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				return repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				return mocks.NewThingRepositoryMock(mc)
 			},
-			placeThingRepoMock: func(mc *minimock.Controller) interfaces.PlaceThingRepository {
-				return repoMocks.NewPlaceThingRepositoryMock(mc)
+			placeThingRepoMock: func(mc *minimock.Controller) PlaceThingRepository {
+				return mocks.NewPlaceThingRepositoryMock(mc)
 			},
 		},
 		{
@@ -151,11 +151,11 @@ func Test_UpdateThingHandler(t *testing.T) {
 				route:  "/v1/things/" + strconv.Itoa(thingID),
 			},
 			resCode: fiber.StatusBadRequest,
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				return repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				return mocks.NewThingRepositoryMock(mc)
 			},
-			placeThingRepoMock: func(mc *minimock.Controller) interfaces.PlaceThingRepository {
-				return repoMocks.NewPlaceThingRepositoryMock(mc)
+			placeThingRepoMock: func(mc *minimock.Controller) PlaceThingRepository {
+				return mocks.NewPlaceThingRepositoryMock(mc)
 			},
 		},
 		{
@@ -175,11 +175,11 @@ func Test_UpdateThingHandler(t *testing.T) {
 					Tag:   "required",
 				},
 			},
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				return repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				return mocks.NewThingRepositoryMock(mc)
 			},
-			placeThingRepoMock: func(mc *minimock.Controller) interfaces.PlaceThingRepository {
-				return repoMocks.NewPlaceThingRepositoryMock(mc)
+			placeThingRepoMock: func(mc *minimock.Controller) PlaceThingRepository {
+				return mocks.NewPlaceThingRepositoryMock(mc)
 			},
 		},
 		{
@@ -199,19 +199,19 @@ func Test_UpdateThingHandler(t *testing.T) {
 					Tag:   "required",
 				},
 			},
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				return repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				return mocks.NewThingRepositoryMock(mc)
 			},
-			placeThingRepoMock: func(mc *minimock.Controller) interfaces.PlaceThingRepository {
-				return repoMocks.NewPlaceThingRepositoryMock(mc)
+			placeThingRepoMock: func(mc *minimock.Controller) PlaceThingRepository {
+				return mocks.NewPlaceThingRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - repository error (get thing)",
 			req:     correctReq,
 			resCode: fiber.StatusBadRequest,
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				mock := repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				mock := mocks.NewThingRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -219,16 +219,16 @@ func Test_UpdateThingHandler(t *testing.T) {
 
 				return mock
 			},
-			placeThingRepoMock: func(mc *minimock.Controller) interfaces.PlaceThingRepository {
-				return repoMocks.NewPlaceThingRepositoryMock(mc)
+			placeThingRepoMock: func(mc *minimock.Controller) PlaceThingRepository {
+				return mocks.NewPlaceThingRepositoryMock(mc)
 			},
 		},
 		{
 			name:    "negative case - repository error (get place thing)",
 			req:     correctReq,
 			resCode: fiber.StatusBadRequest,
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				mock := repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				mock := mocks.NewThingRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -236,8 +236,8 @@ func Test_UpdateThingHandler(t *testing.T) {
 
 				return mock
 			},
-			placeThingRepoMock: func(mc *minimock.Controller) interfaces.PlaceThingRepository {
-				mock := repoMocks.NewPlaceThingRepositoryMock(mc)
+			placeThingRepoMock: func(mc *minimock.Controller) PlaceThingRepository {
+				mock := mocks.NewPlaceThingRepositoryMock(mc)
 
 				mock.GetByThingIDMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -250,8 +250,8 @@ func Test_UpdateThingHandler(t *testing.T) {
 			name:    "negative case - repository error (begin tx)",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				mock := repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				mock := mocks.NewThingRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -261,8 +261,8 @@ func Test_UpdateThingHandler(t *testing.T) {
 
 				return mock
 			},
-			placeThingRepoMock: func(mc *minimock.Controller) interfaces.PlaceThingRepository {
-				mock := repoMocks.NewPlaceThingRepositoryMock(mc)
+			placeThingRepoMock: func(mc *minimock.Controller) PlaceThingRepository {
+				mock := mocks.NewPlaceThingRepositoryMock(mc)
 
 				mock.GetByThingIDMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -275,8 +275,8 @@ func Test_UpdateThingHandler(t *testing.T) {
 			name:    "negative case - repository error (update thing)",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				mock := repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				mock := mocks.NewThingRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -291,8 +291,8 @@ func Test_UpdateThingHandler(t *testing.T) {
 
 				return mock
 			},
-			placeThingRepoMock: func(mc *minimock.Controller) interfaces.PlaceThingRepository {
-				mock := repoMocks.NewPlaceThingRepositoryMock(mc)
+			placeThingRepoMock: func(mc *minimock.Controller) PlaceThingRepository {
+				mock := mocks.NewPlaceThingRepositoryMock(mc)
 
 				mock.GetByThingIDMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -305,8 +305,8 @@ func Test_UpdateThingHandler(t *testing.T) {
 			name:    "negative case - repository error (update place)",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				mock := repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				mock := mocks.NewThingRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -321,8 +321,8 @@ func Test_UpdateThingHandler(t *testing.T) {
 
 				return mock
 			},
-			placeThingRepoMock: func(mc *minimock.Controller) interfaces.PlaceThingRepository {
-				mock := repoMocks.NewPlaceThingRepositoryMock(mc)
+			placeThingRepoMock: func(mc *minimock.Controller) PlaceThingRepository {
+				mock := mocks.NewPlaceThingRepositoryMock(mc)
 
 				mock.GetByThingIDMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -340,8 +340,8 @@ func Test_UpdateThingHandler(t *testing.T) {
 			name:    "negative case - repository error (commit tx)",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				mock := repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				mock := mocks.NewThingRepositoryMock(mc)
 
 				mock.GetMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -358,8 +358,8 @@ func Test_UpdateThingHandler(t *testing.T) {
 
 				return mock
 			},
-			placeThingRepoMock: func(mc *minimock.Controller) interfaces.PlaceThingRepository {
-				mock := repoMocks.NewPlaceThingRepositoryMock(mc)
+			placeThingRepoMock: func(mc *minimock.Controller) PlaceThingRepository {
+				mock := mocks.NewPlaceThingRepositoryMock(mc)
 
 				mock.GetByThingIDMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -377,8 +377,8 @@ func Test_UpdateThingHandler(t *testing.T) {
 			name:    "negative case - repository error (get thing)",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			thingRepoMock: func(mc *minimock.Controller) interfaces.ThingRepository {
-				mock := repoMocks.NewThingRepositoryMock(mc)
+			thingRepoMock: func(mc *minimock.Controller) ThingRepository {
+				mock := mocks.NewThingRepositoryMock(mc)
 
 				mock.GetMock.Set(func(ctx context.Context, thingID int) (*models.Thing, error) {
 					if mock.GetAfterCounter() == 0 {
@@ -398,8 +398,8 @@ func Test_UpdateThingHandler(t *testing.T) {
 
 				return mock
 			},
-			placeThingRepoMock: func(mc *minimock.Controller) interfaces.PlaceThingRepository {
-				mock := repoMocks.NewPlaceThingRepositoryMock(mc)
+			placeThingRepoMock: func(mc *minimock.Controller) PlaceThingRepository {
+				mock := mocks.NewPlaceThingRepositoryMock(mc)
 
 				mock.GetByThingIDMock.Inspect(func(ctx context.Context, id int) {
 					assert.Equal(mc, thingID, id)
@@ -417,10 +417,11 @@ func Test_UpdateThingHandler(t *testing.T) {
 
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			fiberApp := fiber.New()
-			serviceProvider := sp.InitMock(tt.thingRepoMock(mc), tt.placeThingRepoMock(mc))
+			t.Parallel()
 
-			fiberApp.Put("/v1/things/:thingId", UpdateThingHandler(serviceProvider))
+			mc := minimock.NewController(t)
+			fiberApp := fiber.New()
+			fiberApp.Put("/v1/things/:thingId", UpdateThingHandler(tt.thingRepoMock(mc), tt.placeThingRepoMock(mc)))
 
 			fiberReq := httptest.NewRequest(tt.req.method, tt.req.route, helpers.ConvertDataToIOReader(tt.req.body))
 			fiberReq.Header.Add(fiber.HeaderContentType, tt.req.contentType)

+ 29 - 6
internal/api/v1/user/add_user.go

@@ -1,13 +1,33 @@
 package user
 
+//go:generate mkdir -p mocks
+//go:generate rm -rf ./mocks/*_minimock.go
+//go:generate minimock -i AuthService,UserRepository -o ./mocks/ -s "_minimock.go"
+
 import (
+	"context"
 	"strings"
 
-	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/factory"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
 	"github.com/go-playground/validator/v10"
 	"github.com/gofiber/fiber/v2"
+	"github.com/golang-jwt/jwt/v4"
+
+	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/factory"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/models"
+)
+
+type (
+	AuthService interface {
+		GeneratePasswordHash(password string) (string, error)
+		GetClaims(fctx *fiber.Ctx) jwt.MapClaims
+	}
+
+	UserRepository interface {
+		Get(ctx context.Context, username string) (*models.User, error)
+		Add(ctx context.Context, username string, password string) (int, error)
+		Update(ctx context.Context, req models.UpdateUserRequest) error
+	}
 )
 
 // @Router 		/api/v1/users [post]
@@ -20,7 +40,10 @@ import (
 // @security 	APIKey
 // @Accept      json
 // @Produce     json
-func AddUserHandler(sp interfaces.ServiceProvider) fiber.Handler {
+func AddUserHandler(
+	authService AuthService,
+	userRepository UserRepository,
+) fiber.Handler {
 	return func(fctx *fiber.Ctx) error {
 		ctx := fctx.Context()
 		req := dto.AddUserRequest{}
@@ -33,12 +56,12 @@ func AddUserHandler(sp interfaces.ServiceProvider) fiber.Handler {
 			return fctx.Status(fiber.StatusBadRequest).JSON(factory.CreateValidateErrorResponse(err))
 		}
 
-		hash, err := sp.GetAuthService().GeneratePasswordHash(strings.TrimSpace(req.Password))
+		hash, err := authService.GeneratePasswordHash(strings.TrimSpace(req.Password))
 		if err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}
 
-		_, err = sp.GetUserRepository().Add(ctx, strings.TrimSpace(req.Username), hash)
+		_, err = userRepository.Add(ctx, strings.TrimSpace(req.Username), hash)
 		if err != nil {
 			return fiber.NewError(fiber.StatusInternalServerError, err.Error())
 		}

+ 34 - 34
internal/api/v1/user/add_user_test.go

@@ -6,20 +6,20 @@ import (
 	"net/http/httptest"
 	"testing"
 
-	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
-	"git.dmitriygnatenko.ru/dima/homethings/internal/interfaces"
-	repoMocks "git.dmitriygnatenko.ru/dima/homethings/internal/repositories/mocks"
-	sp "git.dmitriygnatenko.ru/dima/homethings/internal/service_provider"
-	authMocks "git.dmitriygnatenko.ru/dima/homethings/internal/services/auth/mocks"
 	"github.com/brianvoe/gofakeit/v6"
 	"github.com/gofiber/fiber/v2"
 	"github.com/gojuno/minimock/v3"
 	"github.com/stretchr/testify/assert"
+
+	API "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/user/mocks"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/dto"
+	"git.dmitriygnatenko.ru/dima/homethings/internal/helpers"
 )
 
-func Test_AddUserHandler(t *testing.T) {
+func TestAddUserHandler(t *testing.T) {
+	t.Parallel()
+
 	type req struct {
 		method      string
 		route       string
@@ -28,7 +28,6 @@ func Test_AddUserHandler(t *testing.T) {
 	}
 
 	var (
-		mc        = minimock.NewController(t)
 		id        = gofakeit.Number(1, 1000)
 		username  = gofakeit.Username()
 		password  = gofakeit.Word()
@@ -50,16 +49,16 @@ func Test_AddUserHandler(t *testing.T) {
 		req             req
 		resCode         int
 		resBody         interface{}
-		userRepoMock    func(mc *minimock.Controller) interfaces.UserRepository
-		authServiceMock func(mc *minimock.Controller) interfaces.Auth
+		userRepoMock    func(mc *minimock.Controller) UserRepository
+		authServiceMock func(mc *minimock.Controller) AuthService
 	}{
 		{
 			name:    "positive case",
 			req:     correctReq,
 			resCode: fiber.StatusOK,
 			resBody: dto.EmptyResponse{},
-			userRepoMock: func(mc *minimock.Controller) interfaces.UserRepository {
-				mock := repoMocks.NewUserRepositoryMock(mc)
+			userRepoMock: func(mc *minimock.Controller) UserRepository {
+				mock := mocks.NewUserRepositoryMock(mc)
 
 				mock.AddMock.Inspect(func(ctx context.Context, reqUsername string, reqPassword string) {
 					assert.Equal(mc, username, reqUsername)
@@ -68,8 +67,8 @@ func Test_AddUserHandler(t *testing.T) {
 
 				return mock
 			},
-			authServiceMock: func(mc *minimock.Controller) interfaces.Auth {
-				mock := authMocks.NewAuthMock(mc)
+			authServiceMock: func(mc *minimock.Controller) AuthService {
+				mock := mocks.NewAuthServiceMock(mc)
 				mock.GeneratePasswordHashMock.Return(password, nil)
 				return mock
 			},
@@ -81,11 +80,11 @@ func Test_AddUserHandler(t *testing.T) {
 				route:  "/v1/users",
 			},
 			resCode: fiber.StatusBadRequest,
-			userRepoMock: func(mc *minimock.Controller) interfaces.UserRepository {
-				return repoMocks.NewUserRepositoryMock(mc)
+			userRepoMock: func(mc *minimock.Controller) UserRepository {
+				return mocks.NewUserRepositoryMock(mc)
 			},
-			authServiceMock: func(mc *minimock.Controller) interfaces.Auth {
-				return authMocks.NewAuthMock(mc)
+			authServiceMock: func(mc *minimock.Controller) AuthService {
+				return mocks.NewAuthServiceMock(mc)
 			},
 		},
 		{
@@ -99,19 +98,19 @@ func Test_AddUserHandler(t *testing.T) {
 				contentType: fiber.MIMEApplicationJSON,
 			},
 			resCode: fiber.StatusBadRequest,
-			userRepoMock: func(mc *minimock.Controller) interfaces.UserRepository {
-				return repoMocks.NewUserRepositoryMock(mc)
+			userRepoMock: func(mc *minimock.Controller) UserRepository {
+				return mocks.NewUserRepositoryMock(mc)
 			},
-			authServiceMock: func(mc *minimock.Controller) interfaces.Auth {
-				return authMocks.NewAuthMock(mc)
+			authServiceMock: func(mc *minimock.Controller) AuthService {
+				return mocks.NewAuthServiceMock(mc)
 			},
 		},
 		{
 			name:    "negative case - repository error",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			userRepoMock: func(mc *minimock.Controller) interfaces.UserRepository {
-				mock := repoMocks.NewUserRepositoryMock(mc)
+			userRepoMock: func(mc *minimock.Controller) UserRepository {
+				mock := mocks.NewUserRepositoryMock(mc)
 
 				mock.AddMock.Inspect(func(ctx context.Context, reqUsername string, reqPassword string) {
 					assert.Equal(mc, username, reqUsername)
@@ -120,8 +119,8 @@ func Test_AddUserHandler(t *testing.T) {
 
 				return mock
 			},
-			authServiceMock: func(mc *minimock.Controller) interfaces.Auth {
-				mock := authMocks.NewAuthMock(mc)
+			authServiceMock: func(mc *minimock.Controller) AuthService {
+				mock := mocks.NewAuthServiceMock(mc)
 				mock.GeneratePasswordHashMock.Return(password, nil)
 				return mock
 			},
@@ -130,11 +129,11 @@ func Test_AddUserHandler(t *testing.T) {
 			name:    "negative case - auth service error",
 			req:     correctReq,
 			resCode: fiber.StatusInternalServerError,
-			userRepoMock: func(mc *minimock.Controller) interfaces.UserRepository {
-				return repoMocks.NewUserRepositoryMock(mc)
+			userRepoMock: func(mc *minimock.Controller) UserRepository {
+				return mocks.NewUserRepositoryMock(mc)
 			},
-			authServiceMock: func(mc *minimock.Controller) interfaces.Auth {
-				mock := authMocks.NewAuthMock(mc)
+			authServiceMock: func(mc *minimock.Controller) AuthService {
+				mock := mocks.NewAuthServiceMock(mc)
 				mock.GeneratePasswordHashMock.Return("", testError)
 				return mock
 			},
@@ -143,10 +142,11 @@ func Test_AddUserHandler(t *testing.T) {
 
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			fiberApp := fiber.New()
-			serviceProvider := sp.InitMock(tt.userRepoMock(mc), tt.authServiceMock(mc))
+			t.Parallel()
 
-			fiberApp.Post("/v1/users", AddUserHandler(serviceProvider))
+			mc := minimock.NewController(t)
+			fiberApp := fiber.New()
+			fiberApp.Post("/v1/users", AddUserHandler(tt.authServiceMock(mc), tt.userRepoMock(mc)))
 
 			fiberReq := httptest.NewRequest(tt.req.method, tt.req.route, helpers.ConvertDataToIOReader(tt.req.body))
 			fiberReq.Header.Add(fiber.HeaderContentType, tt.req.contentType)

+ 671 - 0
internal/api/v1/user/mocks/auth_service_minimock.go

@@ -0,0 +1,671 @@
+// Code generated by http://github.com/gojuno/minimock (v3.3.13). DO NOT EDIT.
+
+package mocks
+
+//go:generate minimock -i git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/user.AuthService -o auth_service_minimock.go -n AuthServiceMock -p mocks
+
+import (
+	"sync"
+	mm_atomic "sync/atomic"
+	mm_time "time"
+
+	"github.com/gofiber/fiber/v2"
+	"github.com/gojuno/minimock/v3"
+	"github.com/golang-jwt/jwt/v4"
+)
+
+// AuthServiceMock implements user.AuthService
+type AuthServiceMock struct {
+	t          minimock.Tester
+	finishOnce sync.Once
+
+	funcGeneratePasswordHash          func(password string) (s1 string, err error)
+	inspectFuncGeneratePasswordHash   func(password string)
+	afterGeneratePasswordHashCounter  uint64
+	beforeGeneratePasswordHashCounter uint64
+	GeneratePasswordHashMock          mAuthServiceMockGeneratePasswordHash
+
+	funcGetClaims          func(fctx *fiber.Ctx) (m1 jwt.MapClaims)
+	inspectFuncGetClaims   func(fctx *fiber.Ctx)
+	afterGetClaimsCounter  uint64
+	beforeGetClaimsCounter uint64
+	GetClaimsMock          mAuthServiceMockGetClaims
+}
+
+// NewAuthServiceMock returns a mock for user.AuthService
+func NewAuthServiceMock(t minimock.Tester) *AuthServiceMock {
+	m := &AuthServiceMock{t: t}
+
+	if controller, ok := t.(minimock.MockController); ok {
+		controller.RegisterMocker(m)
+	}
+
+	m.GeneratePasswordHashMock = mAuthServiceMockGeneratePasswordHash{mock: m}
+	m.GeneratePasswordHashMock.callArgs = []*AuthServiceMockGeneratePasswordHashParams{}
+
+	m.GetClaimsMock = mAuthServiceMockGetClaims{mock: m}
+	m.GetClaimsMock.callArgs = []*AuthServiceMockGetClaimsParams{}
+
+	t.Cleanup(m.MinimockFinish)
+
+	return m
+}
+
+type mAuthServiceMockGeneratePasswordHash struct {
+	optional           bool
+	mock               *AuthServiceMock
+	defaultExpectation *AuthServiceMockGeneratePasswordHashExpectation
+	expectations       []*AuthServiceMockGeneratePasswordHashExpectation
+
+	callArgs []*AuthServiceMockGeneratePasswordHashParams
+	mutex    sync.RWMutex
+
+	expectedInvocations uint64
+}
+
+// AuthServiceMockGeneratePasswordHashExpectation specifies expectation struct of the AuthService.GeneratePasswordHash
+type AuthServiceMockGeneratePasswordHashExpectation struct {
+	mock      *AuthServiceMock
+	params    *AuthServiceMockGeneratePasswordHashParams
+	paramPtrs *AuthServiceMockGeneratePasswordHashParamPtrs
+	results   *AuthServiceMockGeneratePasswordHashResults
+	Counter   uint64
+}
+
+// AuthServiceMockGeneratePasswordHashParams contains parameters of the AuthService.GeneratePasswordHash
+type AuthServiceMockGeneratePasswordHashParams struct {
+	password string
+}
+
+// AuthServiceMockGeneratePasswordHashParamPtrs contains pointers to parameters of the AuthService.GeneratePasswordHash
+type AuthServiceMockGeneratePasswordHashParamPtrs struct {
+	password *string
+}
+
+// AuthServiceMockGeneratePasswordHashResults contains results of the AuthService.GeneratePasswordHash
+type AuthServiceMockGeneratePasswordHashResults struct {
+	s1  string
+	err error
+}
+
+// Marks this method to be optional. The default behavior of any method with Return() is '1 or more', meaning
+// the test will fail minimock's automatic final call check if the mocked method was not called at least once.
+// Optional() makes method check to work in '0 or more' mode.
+// It is NOT RECOMMENDED to use this option unless you really need it, as default behaviour helps to
+// catch the problems when the expected method call is totally skipped during test run.
+func (mmGeneratePasswordHash *mAuthServiceMockGeneratePasswordHash) Optional() *mAuthServiceMockGeneratePasswordHash {
+	mmGeneratePasswordHash.optional = true
+	return mmGeneratePasswordHash
+}
+
+// Expect sets up expected params for AuthService.GeneratePasswordHash
+func (mmGeneratePasswordHash *mAuthServiceMockGeneratePasswordHash) Expect(password string) *mAuthServiceMockGeneratePasswordHash {
+	if mmGeneratePasswordHash.mock.funcGeneratePasswordHash != nil {
+		mmGeneratePasswordHash.mock.t.Fatalf("AuthServiceMock.GeneratePasswordHash mock is already set by Set")
+	}
+
+	if mmGeneratePasswordHash.defaultExpectation == nil {
+		mmGeneratePasswordHash.defaultExpectation = &AuthServiceMockGeneratePasswordHashExpectation{}
+	}
+
+	if mmGeneratePasswordHash.defaultExpectation.paramPtrs != nil {
+		mmGeneratePasswordHash.mock.t.Fatalf("AuthServiceMock.GeneratePasswordHash mock is already set by ExpectParams functions")
+	}
+
+	mmGeneratePasswordHash.defaultExpectation.params = &AuthServiceMockGeneratePasswordHashParams{password}
+	for _, e := range mmGeneratePasswordHash.expectations {
+		if minimock.Equal(e.params, mmGeneratePasswordHash.defaultExpectation.params) {
+			mmGeneratePasswordHash.mock.t.Fatalf("Expectation set by When has same params: %#v", *mmGeneratePasswordHash.defaultExpectation.params)
+		}
+	}
+
+	return mmGeneratePasswordHash
+}
+
+// ExpectPasswordParam1 sets up expected param password for AuthService.GeneratePasswordHash
+func (mmGeneratePasswordHash *mAuthServiceMockGeneratePasswordHash) ExpectPasswordParam1(password string) *mAuthServiceMockGeneratePasswordHash {
+	if mmGeneratePasswordHash.mock.funcGeneratePasswordHash != nil {
+		mmGeneratePasswordHash.mock.t.Fatalf("AuthServiceMock.GeneratePasswordHash mock is already set by Set")
+	}
+
+	if mmGeneratePasswordHash.defaultExpectation == nil {
+		mmGeneratePasswordHash.defaultExpectation = &AuthServiceMockGeneratePasswordHashExpectation{}
+	}
+
+	if mmGeneratePasswordHash.defaultExpectation.params != nil {
+		mmGeneratePasswordHash.mock.t.Fatalf("AuthServiceMock.GeneratePasswordHash mock is already set by Expect")
+	}
+
+	if mmGeneratePasswordHash.defaultExpectation.paramPtrs == nil {
+		mmGeneratePasswordHash.defaultExpectation.paramPtrs = &AuthServiceMockGeneratePasswordHashParamPtrs{}
+	}
+	mmGeneratePasswordHash.defaultExpectation.paramPtrs.password = &password
+
+	return mmGeneratePasswordHash
+}
+
+// Inspect accepts an inspector function that has same arguments as the AuthService.GeneratePasswordHash
+func (mmGeneratePasswordHash *mAuthServiceMockGeneratePasswordHash) Inspect(f func(password string)) *mAuthServiceMockGeneratePasswordHash {
+	if mmGeneratePasswordHash.mock.inspectFuncGeneratePasswordHash != nil {
+		mmGeneratePasswordHash.mock.t.Fatalf("Inspect function is already set for AuthServiceMock.GeneratePasswordHash")
+	}
+
+	mmGeneratePasswordHash.mock.inspectFuncGeneratePasswordHash = f
+
+	return mmGeneratePasswordHash
+}
+
+// Return sets up results that will be returned by AuthService.GeneratePasswordHash
+func (mmGeneratePasswordHash *mAuthServiceMockGeneratePasswordHash) Return(s1 string, err error) *AuthServiceMock {
+	if mmGeneratePasswordHash.mock.funcGeneratePasswordHash != nil {
+		mmGeneratePasswordHash.mock.t.Fatalf("AuthServiceMock.GeneratePasswordHash mock is already set by Set")
+	}
+
+	if mmGeneratePasswordHash.defaultExpectation == nil {
+		mmGeneratePasswordHash.defaultExpectation = &AuthServiceMockGeneratePasswordHashExpectation{mock: mmGeneratePasswordHash.mock}
+	}
+	mmGeneratePasswordHash.defaultExpectation.results = &AuthServiceMockGeneratePasswordHashResults{s1, err}
+	return mmGeneratePasswordHash.mock
+}
+
+// Set uses given function f to mock the AuthService.GeneratePasswordHash method
+func (mmGeneratePasswordHash *mAuthServiceMockGeneratePasswordHash) Set(f func(password string) (s1 string, err error)) *AuthServiceMock {
+	if mmGeneratePasswordHash.defaultExpectation != nil {
+		mmGeneratePasswordHash.mock.t.Fatalf("Default expectation is already set for the AuthService.GeneratePasswordHash method")
+	}
+
+	if len(mmGeneratePasswordHash.expectations) > 0 {
+		mmGeneratePasswordHash.mock.t.Fatalf("Some expectations are already set for the AuthService.GeneratePasswordHash method")
+	}
+
+	mmGeneratePasswordHash.mock.funcGeneratePasswordHash = f
+	return mmGeneratePasswordHash.mock
+}
+
+// When sets expectation for the AuthService.GeneratePasswordHash which will trigger the result defined by the following
+// Then helper
+func (mmGeneratePasswordHash *mAuthServiceMockGeneratePasswordHash) When(password string) *AuthServiceMockGeneratePasswordHashExpectation {
+	if mmGeneratePasswordHash.mock.funcGeneratePasswordHash != nil {
+		mmGeneratePasswordHash.mock.t.Fatalf("AuthServiceMock.GeneratePasswordHash mock is already set by Set")
+	}
+
+	expectation := &AuthServiceMockGeneratePasswordHashExpectation{
+		mock:   mmGeneratePasswordHash.mock,
+		params: &AuthServiceMockGeneratePasswordHashParams{password},
+	}
+	mmGeneratePasswordHash.expectations = append(mmGeneratePasswordHash.expectations, expectation)
+	return expectation
+}
+
+// Then sets up AuthService.GeneratePasswordHash return parameters for the expectation previously defined by the When method
+func (e *AuthServiceMockGeneratePasswordHashExpectation) Then(s1 string, err error) *AuthServiceMock {
+	e.results = &AuthServiceMockGeneratePasswordHashResults{s1, err}
+	return e.mock
+}
+
+// Times sets number of times AuthService.GeneratePasswordHash should be invoked
+func (mmGeneratePasswordHash *mAuthServiceMockGeneratePasswordHash) Times(n uint64) *mAuthServiceMockGeneratePasswordHash {
+	if n == 0 {
+		mmGeneratePasswordHash.mock.t.Fatalf("Times of AuthServiceMock.GeneratePasswordHash mock can not be zero")
+	}
+	mm_atomic.StoreUint64(&mmGeneratePasswordHash.expectedInvocations, n)
+	return mmGeneratePasswordHash
+}
+
+func (mmGeneratePasswordHash *mAuthServiceMockGeneratePasswordHash) invocationsDone() bool {
+	if len(mmGeneratePasswordHash.expectations) == 0 && mmGeneratePasswordHash.defaultExpectation == nil && mmGeneratePasswordHash.mock.funcGeneratePasswordHash == nil {
+		return true
+	}
+
+	totalInvocations := mm_atomic.LoadUint64(&mmGeneratePasswordHash.mock.afterGeneratePasswordHashCounter)
+	expectedInvocations := mm_atomic.LoadUint64(&mmGeneratePasswordHash.expectedInvocations)
+
+	return totalInvocations > 0 && (expectedInvocations == 0 || expectedInvocations == totalInvocations)
+}
+
+// GeneratePasswordHash implements user.AuthService
+func (mmGeneratePasswordHash *AuthServiceMock) GeneratePasswordHash(password string) (s1 string, err error) {
+	mm_atomic.AddUint64(&mmGeneratePasswordHash.beforeGeneratePasswordHashCounter, 1)
+	defer mm_atomic.AddUint64(&mmGeneratePasswordHash.afterGeneratePasswordHashCounter, 1)
+
+	if mmGeneratePasswordHash.inspectFuncGeneratePasswordHash != nil {
+		mmGeneratePasswordHash.inspectFuncGeneratePasswordHash(password)
+	}
+
+	mm_params := AuthServiceMockGeneratePasswordHashParams{password}
+
+	// Record call args
+	mmGeneratePasswordHash.GeneratePasswordHashMock.mutex.Lock()
+	mmGeneratePasswordHash.GeneratePasswordHashMock.callArgs = append(mmGeneratePasswordHash.GeneratePasswordHashMock.callArgs, &mm_params)
+	mmGeneratePasswordHash.GeneratePasswordHashMock.mutex.Unlock()
+
+	for _, e := range mmGeneratePasswordHash.GeneratePasswordHashMock.expectations {
+		if minimock.Equal(*e.params, mm_params) {
+			mm_atomic.AddUint64(&e.Counter, 1)
+			return e.results.s1, e.results.err
+		}
+	}
+
+	if mmGeneratePasswordHash.GeneratePasswordHashMock.defaultExpectation != nil {
+		mm_atomic.AddUint64(&mmGeneratePasswordHash.GeneratePasswordHashMock.defaultExpectation.Counter, 1)
+		mm_want := mmGeneratePasswordHash.GeneratePasswordHashMock.defaultExpectation.params
+		mm_want_ptrs := mmGeneratePasswordHash.GeneratePasswordHashMock.defaultExpectation.paramPtrs
+
+		mm_got := AuthServiceMockGeneratePasswordHashParams{password}
+
+		if mm_want_ptrs != nil {
+
+			if mm_want_ptrs.password != nil && !minimock.Equal(*mm_want_ptrs.password, mm_got.password) {
+				mmGeneratePasswordHash.t.Errorf("AuthServiceMock.GeneratePasswordHash got unexpected parameter password, want: %#v, got: %#v%s\n", *mm_want_ptrs.password, mm_got.password, minimock.Diff(*mm_want_ptrs.password, mm_got.password))
+			}
+
+		} else if mm_want != nil && !minimock.Equal(*mm_want, mm_got) {
+			mmGeneratePasswordHash.t.Errorf("AuthServiceMock.GeneratePasswordHash got unexpected parameters, want: %#v, got: %#v%s\n", *mm_want, mm_got, minimock.Diff(*mm_want, mm_got))
+		}
+
+		mm_results := mmGeneratePasswordHash.GeneratePasswordHashMock.defaultExpectation.results
+		if mm_results == nil {
+			mmGeneratePasswordHash.t.Fatal("No results are set for the AuthServiceMock.GeneratePasswordHash")
+		}
+		return (*mm_results).s1, (*mm_results).err
+	}
+	if mmGeneratePasswordHash.funcGeneratePasswordHash != nil {
+		return mmGeneratePasswordHash.funcGeneratePasswordHash(password)
+	}
+	mmGeneratePasswordHash.t.Fatalf("Unexpected call to AuthServiceMock.GeneratePasswordHash. %v", password)
+	return
+}
+
+// GeneratePasswordHashAfterCounter returns a count of finished AuthServiceMock.GeneratePasswordHash invocations
+func (mmGeneratePasswordHash *AuthServiceMock) GeneratePasswordHashAfterCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmGeneratePasswordHash.afterGeneratePasswordHashCounter)
+}
+
+// GeneratePasswordHashBeforeCounter returns a count of AuthServiceMock.GeneratePasswordHash invocations
+func (mmGeneratePasswordHash *AuthServiceMock) GeneratePasswordHashBeforeCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmGeneratePasswordHash.beforeGeneratePasswordHashCounter)
+}
+
+// Calls returns a list of arguments used in each call to AuthServiceMock.GeneratePasswordHash.
+// The list is in the same order as the calls were made (i.e. recent calls have a higher index)
+func (mmGeneratePasswordHash *mAuthServiceMockGeneratePasswordHash) Calls() []*AuthServiceMockGeneratePasswordHashParams {
+	mmGeneratePasswordHash.mutex.RLock()
+
+	argCopy := make([]*AuthServiceMockGeneratePasswordHashParams, len(mmGeneratePasswordHash.callArgs))
+	copy(argCopy, mmGeneratePasswordHash.callArgs)
+
+	mmGeneratePasswordHash.mutex.RUnlock()
+
+	return argCopy
+}
+
+// MinimockGeneratePasswordHashDone returns true if the count of the GeneratePasswordHash invocations corresponds
+// the number of defined expectations
+func (m *AuthServiceMock) MinimockGeneratePasswordHashDone() bool {
+	if m.GeneratePasswordHashMock.optional {
+		// Optional methods provide '0 or more' call count restriction.
+		return true
+	}
+
+	for _, e := range m.GeneratePasswordHashMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			return false
+		}
+	}
+
+	return m.GeneratePasswordHashMock.invocationsDone()
+}
+
+// MinimockGeneratePasswordHashInspect logs each unmet expectation
+func (m *AuthServiceMock) MinimockGeneratePasswordHashInspect() {
+	for _, e := range m.GeneratePasswordHashMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			m.t.Errorf("Expected call to AuthServiceMock.GeneratePasswordHash with params: %#v", *e.params)
+		}
+	}
+
+	afterGeneratePasswordHashCounter := mm_atomic.LoadUint64(&m.afterGeneratePasswordHashCounter)
+	// if default expectation was set then invocations count should be greater than zero
+	if m.GeneratePasswordHashMock.defaultExpectation != nil && afterGeneratePasswordHashCounter < 1 {
+		if m.GeneratePasswordHashMock.defaultExpectation.params == nil {
+			m.t.Error("Expected call to AuthServiceMock.GeneratePasswordHash")
+		} else {
+			m.t.Errorf("Expected call to AuthServiceMock.GeneratePasswordHash with params: %#v", *m.GeneratePasswordHashMock.defaultExpectation.params)
+		}
+	}
+	// if func was set then invocations count should be greater than zero
+	if m.funcGeneratePasswordHash != nil && afterGeneratePasswordHashCounter < 1 {
+		m.t.Error("Expected call to AuthServiceMock.GeneratePasswordHash")
+	}
+
+	if !m.GeneratePasswordHashMock.invocationsDone() && afterGeneratePasswordHashCounter > 0 {
+		m.t.Errorf("Expected %d calls to AuthServiceMock.GeneratePasswordHash but found %d calls",
+			mm_atomic.LoadUint64(&m.GeneratePasswordHashMock.expectedInvocations), afterGeneratePasswordHashCounter)
+	}
+}
+
+type mAuthServiceMockGetClaims struct {
+	optional           bool
+	mock               *AuthServiceMock
+	defaultExpectation *AuthServiceMockGetClaimsExpectation
+	expectations       []*AuthServiceMockGetClaimsExpectation
+
+	callArgs []*AuthServiceMockGetClaimsParams
+	mutex    sync.RWMutex
+
+	expectedInvocations uint64
+}
+
+// AuthServiceMockGetClaimsExpectation specifies expectation struct of the AuthService.GetClaims
+type AuthServiceMockGetClaimsExpectation struct {
+	mock      *AuthServiceMock
+	params    *AuthServiceMockGetClaimsParams
+	paramPtrs *AuthServiceMockGetClaimsParamPtrs
+	results   *AuthServiceMockGetClaimsResults
+	Counter   uint64
+}
+
+// AuthServiceMockGetClaimsParams contains parameters of the AuthService.GetClaims
+type AuthServiceMockGetClaimsParams struct {
+	fctx *fiber.Ctx
+}
+
+// AuthServiceMockGetClaimsParamPtrs contains pointers to parameters of the AuthService.GetClaims
+type AuthServiceMockGetClaimsParamPtrs struct {
+	fctx **fiber.Ctx
+}
+
+// AuthServiceMockGetClaimsResults contains results of the AuthService.GetClaims
+type AuthServiceMockGetClaimsResults struct {
+	m1 jwt.MapClaims
+}
+
+// Marks this method to be optional. The default behavior of any method with Return() is '1 or more', meaning
+// the test will fail minimock's automatic final call check if the mocked method was not called at least once.
+// Optional() makes method check to work in '0 or more' mode.
+// It is NOT RECOMMENDED to use this option unless you really need it, as default behaviour helps to
+// catch the problems when the expected method call is totally skipped during test run.
+func (mmGetClaims *mAuthServiceMockGetClaims) Optional() *mAuthServiceMockGetClaims {
+	mmGetClaims.optional = true
+	return mmGetClaims
+}
+
+// Expect sets up expected params for AuthService.GetClaims
+func (mmGetClaims *mAuthServiceMockGetClaims) Expect(fctx *fiber.Ctx) *mAuthServiceMockGetClaims {
+	if mmGetClaims.mock.funcGetClaims != nil {
+		mmGetClaims.mock.t.Fatalf("AuthServiceMock.GetClaims mock is already set by Set")
+	}
+
+	if mmGetClaims.defaultExpectation == nil {
+		mmGetClaims.defaultExpectation = &AuthServiceMockGetClaimsExpectation{}
+	}
+
+	if mmGetClaims.defaultExpectation.paramPtrs != nil {
+		mmGetClaims.mock.t.Fatalf("AuthServiceMock.GetClaims mock is already set by ExpectParams functions")
+	}
+
+	mmGetClaims.defaultExpectation.params = &AuthServiceMockGetClaimsParams{fctx}
+	for _, e := range mmGetClaims.expectations {
+		if minimock.Equal(e.params, mmGetClaims.defaultExpectation.params) {
+			mmGetClaims.mock.t.Fatalf("Expectation set by When has same params: %#v", *mmGetClaims.defaultExpectation.params)
+		}
+	}
+
+	return mmGetClaims
+}
+
+// ExpectFctxParam1 sets up expected param fctx for AuthService.GetClaims
+func (mmGetClaims *mAuthServiceMockGetClaims) ExpectFctxParam1(fctx *fiber.Ctx) *mAuthServiceMockGetClaims {
+	if mmGetClaims.mock.funcGetClaims != nil {
+		mmGetClaims.mock.t.Fatalf("AuthServiceMock.GetClaims mock is already set by Set")
+	}
+
+	if mmGetClaims.defaultExpectation == nil {
+		mmGetClaims.defaultExpectation = &AuthServiceMockGetClaimsExpectation{}
+	}
+
+	if mmGetClaims.defaultExpectation.params != nil {
+		mmGetClaims.mock.t.Fatalf("AuthServiceMock.GetClaims mock is already set by Expect")
+	}
+
+	if mmGetClaims.defaultExpectation.paramPtrs == nil {
+		mmGetClaims.defaultExpectation.paramPtrs = &AuthServiceMockGetClaimsParamPtrs{}
+	}
+	mmGetClaims.defaultExpectation.paramPtrs.fctx = &fctx
+
+	return mmGetClaims
+}
+
+// Inspect accepts an inspector function that has same arguments as the AuthService.GetClaims
+func (mmGetClaims *mAuthServiceMockGetClaims) Inspect(f func(fctx *fiber.Ctx)) *mAuthServiceMockGetClaims {
+	if mmGetClaims.mock.inspectFuncGetClaims != nil {
+		mmGetClaims.mock.t.Fatalf("Inspect function is already set for AuthServiceMock.GetClaims")
+	}
+
+	mmGetClaims.mock.inspectFuncGetClaims = f
+
+	return mmGetClaims
+}
+
+// Return sets up results that will be returned by AuthService.GetClaims
+func (mmGetClaims *mAuthServiceMockGetClaims) Return(m1 jwt.MapClaims) *AuthServiceMock {
+	if mmGetClaims.mock.funcGetClaims != nil {
+		mmGetClaims.mock.t.Fatalf("AuthServiceMock.GetClaims mock is already set by Set")
+	}
+
+	if mmGetClaims.defaultExpectation == nil {
+		mmGetClaims.defaultExpectation = &AuthServiceMockGetClaimsExpectation{mock: mmGetClaims.mock}
+	}
+	mmGetClaims.defaultExpectation.results = &AuthServiceMockGetClaimsResults{m1}
+	return mmGetClaims.mock
+}
+
+// Set uses given function f to mock the AuthService.GetClaims method
+func (mmGetClaims *mAuthServiceMockGetClaims) Set(f func(fctx *fiber.Ctx) (m1 jwt.MapClaims)) *AuthServiceMock {
+	if mmGetClaims.defaultExpectation != nil {
+		mmGetClaims.mock.t.Fatalf("Default expectation is already set for the AuthService.GetClaims method")
+	}
+
+	if len(mmGetClaims.expectations) > 0 {
+		mmGetClaims.mock.t.Fatalf("Some expectations are already set for the AuthService.GetClaims method")
+	}
+
+	mmGetClaims.mock.funcGetClaims = f
+	return mmGetClaims.mock
+}
+
+// When sets expectation for the AuthService.GetClaims which will trigger the result defined by the following
+// Then helper
+func (mmGetClaims *mAuthServiceMockGetClaims) When(fctx *fiber.Ctx) *AuthServiceMockGetClaimsExpectation {
+	if mmGetClaims.mock.funcGetClaims != nil {
+		mmGetClaims.mock.t.Fatalf("AuthServiceMock.GetClaims mock is already set by Set")
+	}
+
+	expectation := &AuthServiceMockGetClaimsExpectation{
+		mock:   mmGetClaims.mock,
+		params: &AuthServiceMockGetClaimsParams{fctx},
+	}
+	mmGetClaims.expectations = append(mmGetClaims.expectations, expectation)
+	return expectation
+}
+
+// Then sets up AuthService.GetClaims return parameters for the expectation previously defined by the When method
+func (e *AuthServiceMockGetClaimsExpectation) Then(m1 jwt.MapClaims) *AuthServiceMock {
+	e.results = &AuthServiceMockGetClaimsResults{m1}
+	return e.mock
+}
+
+// Times sets number of times AuthService.GetClaims should be invoked
+func (mmGetClaims *mAuthServiceMockGetClaims) Times(n uint64) *mAuthServiceMockGetClaims {
+	if n == 0 {
+		mmGetClaims.mock.t.Fatalf("Times of AuthServiceMock.GetClaims mock can not be zero")
+	}
+	mm_atomic.StoreUint64(&mmGetClaims.expectedInvocations, n)
+	return mmGetClaims
+}
+
+func (mmGetClaims *mAuthServiceMockGetClaims) invocationsDone() bool {
+	if len(mmGetClaims.expectations) == 0 && mmGetClaims.defaultExpectation == nil && mmGetClaims.mock.funcGetClaims == nil {
+		return true
+	}
+
+	totalInvocations := mm_atomic.LoadUint64(&mmGetClaims.mock.afterGetClaimsCounter)
+	expectedInvocations := mm_atomic.LoadUint64(&mmGetClaims.expectedInvocations)
+
+	return totalInvocations > 0 && (expectedInvocations == 0 || expectedInvocations == totalInvocations)
+}
+
+// GetClaims implements user.AuthService
+func (mmGetClaims *AuthServiceMock) GetClaims(fctx *fiber.Ctx) (m1 jwt.MapClaims) {
+	mm_atomic.AddUint64(&mmGetClaims.beforeGetClaimsCounter, 1)
+	defer mm_atomic.AddUint64(&mmGetClaims.afterGetClaimsCounter, 1)
+
+	if mmGetClaims.inspectFuncGetClaims != nil {
+		mmGetClaims.inspectFuncGetClaims(fctx)
+	}
+
+	mm_params := AuthServiceMockGetClaimsParams{fctx}
+
+	// Record call args
+	mmGetClaims.GetClaimsMock.mutex.Lock()
+	mmGetClaims.GetClaimsMock.callArgs = append(mmGetClaims.GetClaimsMock.callArgs, &mm_params)
+	mmGetClaims.GetClaimsMock.mutex.Unlock()
+
+	for _, e := range mmGetClaims.GetClaimsMock.expectations {
+		if minimock.Equal(*e.params, mm_params) {
+			mm_atomic.AddUint64(&e.Counter, 1)
+			return e.results.m1
+		}
+	}
+
+	if mmGetClaims.GetClaimsMock.defaultExpectation != nil {
+		mm_atomic.AddUint64(&mmGetClaims.GetClaimsMock.defaultExpectation.Counter, 1)
+		mm_want := mmGetClaims.GetClaimsMock.defaultExpectation.params
+		mm_want_ptrs := mmGetClaims.GetClaimsMock.defaultExpectation.paramPtrs
+
+		mm_got := AuthServiceMockGetClaimsParams{fctx}
+
+		if mm_want_ptrs != nil {
+
+			if mm_want_ptrs.fctx != nil && !minimock.Equal(*mm_want_ptrs.fctx, mm_got.fctx) {
+				mmGetClaims.t.Errorf("AuthServiceMock.GetClaims got unexpected parameter fctx, want: %#v, got: %#v%s\n", *mm_want_ptrs.fctx, mm_got.fctx, minimock.Diff(*mm_want_ptrs.fctx, mm_got.fctx))
+			}
+
+		} else if mm_want != nil && !minimock.Equal(*mm_want, mm_got) {
+			mmGetClaims.t.Errorf("AuthServiceMock.GetClaims got unexpected parameters, want: %#v, got: %#v%s\n", *mm_want, mm_got, minimock.Diff(*mm_want, mm_got))
+		}
+
+		mm_results := mmGetClaims.GetClaimsMock.defaultExpectation.results
+		if mm_results == nil {
+			mmGetClaims.t.Fatal("No results are set for the AuthServiceMock.GetClaims")
+		}
+		return (*mm_results).m1
+	}
+	if mmGetClaims.funcGetClaims != nil {
+		return mmGetClaims.funcGetClaims(fctx)
+	}
+	mmGetClaims.t.Fatalf("Unexpected call to AuthServiceMock.GetClaims. %v", fctx)
+	return
+}
+
+// GetClaimsAfterCounter returns a count of finished AuthServiceMock.GetClaims invocations
+func (mmGetClaims *AuthServiceMock) GetClaimsAfterCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmGetClaims.afterGetClaimsCounter)
+}
+
+// GetClaimsBeforeCounter returns a count of AuthServiceMock.GetClaims invocations
+func (mmGetClaims *AuthServiceMock) GetClaimsBeforeCounter() uint64 {
+	return mm_atomic.LoadUint64(&mmGetClaims.beforeGetClaimsCounter)
+}
+
+// Calls returns a list of arguments used in each call to AuthServiceMock.GetClaims.
+// The list is in the same order as the calls were made (i.e. recent calls have a higher index)
+func (mmGetClaims *mAuthServiceMockGetClaims) Calls() []*AuthServiceMockGetClaimsParams {
+	mmGetClaims.mutex.RLock()
+
+	argCopy := make([]*AuthServiceMockGetClaimsParams, len(mmGetClaims.callArgs))
+	copy(argCopy, mmGetClaims.callArgs)
+
+	mmGetClaims.mutex.RUnlock()
+
+	return argCopy
+}
+
+// MinimockGetClaimsDone returns true if the count of the GetClaims invocations corresponds
+// the number of defined expectations
+func (m *AuthServiceMock) MinimockGetClaimsDone() bool {
+	if m.GetClaimsMock.optional {
+		// Optional methods provide '0 or more' call count restriction.
+		return true
+	}
+
+	for _, e := range m.GetClaimsMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			return false
+		}
+	}
+
+	return m.GetClaimsMock.invocationsDone()
+}
+
+// MinimockGetClaimsInspect logs each unmet expectation
+func (m *AuthServiceMock) MinimockGetClaimsInspect() {
+	for _, e := range m.GetClaimsMock.expectations {
+		if mm_atomic.LoadUint64(&e.Counter) < 1 {
+			m.t.Errorf("Expected call to AuthServiceMock.GetClaims with params: %#v", *e.params)
+		}
+	}
+
+	afterGetClaimsCounter := mm_atomic.LoadUint64(&m.afterGetClaimsCounter)
+	// if default expectation was set then invocations count should be greater than zero
+	if m.GetClaimsMock.defaultExpectation != nil && afterGetClaimsCounter < 1 {
+		if m.GetClaimsMock.defaultExpectation.params == nil {
+			m.t.Error("Expected call to AuthServiceMock.GetClaims")
+		} else {
+			m.t.Errorf("Expected call to AuthServiceMock.GetClaims with params: %#v", *m.GetClaimsMock.defaultExpectation.params)
+		}
+	}
+	// if func was set then invocations count should be greater than zero
+	if m.funcGetClaims != nil && afterGetClaimsCounter < 1 {
+		m.t.Error("Expected call to AuthServiceMock.GetClaims")
+	}
+
+	if !m.GetClaimsMock.invocationsDone() && afterGetClaimsCounter > 0 {
+		m.t.Errorf("Expected %d calls to AuthServiceMock.GetClaims but found %d calls",
+			mm_atomic.LoadUint64(&m.GetClaimsMock.expectedInvocations), afterGetClaimsCounter)
+	}
+}
+
+// MinimockFinish checks that all mocked methods have been called the expected number of times
+func (m *AuthServiceMock) MinimockFinish() {
+	m.finishOnce.Do(func() {
+		if !m.minimockDone() {
+			m.MinimockGeneratePasswordHashInspect()
+
+			m.MinimockGetClaimsInspect()
+		}
+	})
+}
+
+// MinimockWait waits for all mocked methods to be called the expected number of times
+func (m *AuthServiceMock) MinimockWait(timeout mm_time.Duration) {
+	timeoutCh := mm_time.After(timeout)
+	for {
+		if m.minimockDone() {
+			return
+		}
+		select {
+		case <-timeoutCh:
+			m.MinimockFinish()
+			return
+		case <-mm_time.After(10 * mm_time.Millisecond):
+		}
+	}
+}
+
+func (m *AuthServiceMock) minimockDone() bool {
+	done := true
+	return done &&
+		m.MinimockGeneratePasswordHashDone() &&
+		m.MinimockGetClaimsDone()
+}

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini