From 25b221b1eb0e155926d115a24e48e56924656e4f Mon Sep 17 00:00:00 2001 From: Daniel Giurgiu Date: Wed, 28 Aug 2024 10:33:32 +0300 Subject: [PATCH] Add unit testing for Main handler --- api/coverage.out | 329 ----------------------------------------------- api/go.mod | 1 + api/go.sum | 2 + api/main_test.go | 206 +++++++++++++++++++++++++++-- 4 files changed, 198 insertions(+), 340 deletions(-) delete mode 100644 api/coverage.out diff --git a/api/coverage.out b/api/coverage.out deleted file mode 100644 index 4302565..0000000 --- a/api/coverage.out +++ /dev/null @@ -1,329 +0,0 @@ -mode: set -mymodule/auth.go:32.46,33.54 1 0 -mymodule/auth.go:33.54,41.70 4 0 -mymodule/auth.go:41.70,45.4 3 0 -mymodule/auth.go:47.3,50.41 4 0 -mymodule/auth.go:50.41,54.4 3 0 -mymodule/auth.go:56.3,56.26 1 0 -mymodule/auth.go:56.26,60.4 3 0 -mymodule/auth.go:62.3,63.17 2 0 -mymodule/auth.go:63.17,67.4 3 0 -mymodule/auth.go:69.3,72.17 3 0 -mymodule/auth.go:72.17,76.4 3 0 -mymodule/auth.go:78.3,79.90 2 0 -mymodule/auth.go:83.45,84.54 1 0 -mymodule/auth.go:84.54,93.70 4 0 -mymodule/auth.go:93.70,97.4 3 0 -mymodule/auth.go:99.3,104.27 5 0 -mymodule/auth.go:104.27,108.4 3 0 -mymodule/auth.go:110.3,110.17 1 0 -mymodule/auth.go:110.17,114.4 3 0 -mymodule/auth.go:116.3,117.49 2 0 -mymodule/auth.go:117.49,121.4 3 0 -mymodule/auth.go:123.3,129.34 3 0 -mymodule/main.go:66.13,70.16 4 0 -mymodule/main.go:70.16,72.3 1 0 -mymodule/main.go:74.2,81.16 7 0 -mymodule/main.go:81.16,83.3 1 0 -mymodule/main.go:84.2,95.16 7 0 -mymodule/main.go:95.16,97.3 1 0 -mymodule/main.go:100.42,131.2 28 0 -mymodule/main.go:133.46,134.48 1 0 -mymodule/main.go:134.48,136.3 1 0 -mymodule/main.go:137.2,137.21 1 0 -mymodule/main.go:140.81,148.16 4 0 -mymodule/main.go:148.16,150.3 1 0 -mymodule/main.go:153.2,154.16 2 0 -mymodule/main.go:154.16,156.3 1 0 -mymodule/main.go:157.2,158.16 2 0 -mymodule/main.go:162.51,164.2 1 0 -mymodule/main.go:167.51,169.2 1 0 -mymodule/main.go:172.47,173.54 1 1 -mymodule/main.go:173.54,188.17 3 0 -mymodule/main.go:188.17,191.4 2 0 -mymodule/main.go:192.3,194.19 3 0 -mymodule/main.go:194.19,196.182 2 0 -mymodule/main.go:196.182,199.5 2 0 -mymodule/main.go:201.4,201.31 1 0 -mymodule/main.go:203.3,203.36 1 0 -mymodule/main.go:203.36,206.4 2 0 -mymodule/main.go:207.3,207.35 1 0 -mymodule/main.go:211.47,212.54 1 1 -mymodule/main.go:212.54,214.18 2 1 -mymodule/main.go:214.18,217.4 2 0 -mymodule/main.go:219.3,234.17 3 1 -mymodule/main.go:234.17,237.4 2 0 -mymodule/main.go:238.3,241.19 3 1 -mymodule/main.go:241.19,243.182 2 1 -mymodule/main.go:243.182,246.5 2 0 -mymodule/main.go:248.4,248.31 1 1 -mymodule/main.go:250.3,250.36 1 1 -mymodule/main.go:250.36,253.4 2 0 -mymodule/main.go:254.3,255.35 2 1 -mymodule/main.go:259.49,260.54 1 1 -mymodule/main.go:260.54,262.18 2 1 -mymodule/main.go:262.18,265.4 2 0 -mymodule/main.go:267.3,268.17 2 1 -mymodule/main.go:268.17,271.4 2 0 -mymodule/main.go:272.3,275.19 3 1 -mymodule/main.go:275.19,277.100 2 1 -mymodule/main.go:277.100,280.5 2 0 -mymodule/main.go:281.4,281.37 1 1 -mymodule/main.go:284.3,285.60 2 1 -mymodule/main.go:285.60,287.4 1 0 -mymodule/main.go:291.46,292.54 1 1 -mymodule/main.go:292.54,294.17 2 1 -mymodule/main.go:294.17,297.4 2 0 -mymodule/main.go:298.3,301.19 3 1 -mymodule/main.go:301.19,303.100 2 1 -mymodule/main.go:303.100,306.5 2 0 -mymodule/main.go:307.4,307.37 1 1 -mymodule/main.go:309.3,309.36 1 1 -mymodule/main.go:309.36,312.4 2 0 -mymodule/main.go:314.3,314.37 1 1 -mymodule/main.go:319.54,320.54 1 1 -mymodule/main.go:320.54,328.17 3 1 -mymodule/main.go:328.17,331.4 2 0 -mymodule/main.go:333.3,336.19 3 1 -mymodule/main.go:336.19,338.95 2 1 -mymodule/main.go:338.95,341.5 2 0 -mymodule/main.go:343.4,350.57 2 1 -mymodule/main.go:353.3,353.36 1 1 -mymodule/main.go:353.36,356.4 2 0 -mymodule/main.go:358.3,358.45 1 1 -mymodule/main.go:363.54,364.54 1 1 -mymodule/main.go:364.54,368.17 4 1 -mymodule/main.go:368.17,371.4 2 0 -mymodule/main.go:373.3,382.17 3 1 -mymodule/main.go:382.17,385.4 2 0 -mymodule/main.go:386.3,391.19 4 1 -mymodule/main.go:391.19,392.109 1 1 -mymodule/main.go:392.109,395.5 2 0 -mymodule/main.go:396.4,399.6 1 1 -mymodule/main.go:402.3,402.36 1 1 -mymodule/main.go:402.36,405.4 2 0 -mymodule/main.go:407.3,420.17 3 1 -mymodule/main.go:420.17,422.4 1 0 -mymodule/main.go:427.47,428.54 1 1 -mymodule/main.go:428.54,431.17 3 1 -mymodule/main.go:431.17,434.4 2 0 -mymodule/main.go:435.3,451.17 3 1 -mymodule/main.go:451.17,454.4 2 0 -mymodule/main.go:455.3,458.19 3 1 -mymodule/main.go:458.19,460.182 2 1 -mymodule/main.go:460.182,463.5 2 0 -mymodule/main.go:465.4,465.31 1 1 -mymodule/main.go:468.3,468.36 1 1 -mymodule/main.go:468.36,471.4 2 0 -mymodule/main.go:473.3,473.22 1 1 -mymodule/main.go:473.22,476.4 2 0 -mymodule/main.go:478.3,478.38 1 1 -mymodule/main.go:482.58,483.54 1 1 -mymodule/main.go:483.54,485.19 2 1 -mymodule/main.go:485.19,488.4 2 0 -mymodule/main.go:490.3,498.17 3 1 -mymodule/main.go:498.17,501.4 2 0 -mymodule/main.go:502.3,505.19 3 1 -mymodule/main.go:505.19,507.100 2 1 -mymodule/main.go:507.100,510.5 2 0 -mymodule/main.go:511.4,511.49 1 1 -mymodule/main.go:514.3,514.36 1 1 -mymodule/main.go:514.36,517.4 2 0 -mymodule/main.go:519.3,519.28 1 1 -mymodule/main.go:519.28,522.4 2 0 -mymodule/main.go:524.3,524.41 1 1 -mymodule/main.go:529.53,530.54 1 1 -mymodule/main.go:530.54,533.17 3 1 -mymodule/main.go:533.17,537.4 3 0 -mymodule/main.go:538.3,541.19 3 1 -mymodule/main.go:541.19,543.100 2 1 -mymodule/main.go:543.100,547.5 3 0 -mymodule/main.go:548.4,548.49 1 1 -mymodule/main.go:550.3,550.36 1 1 -mymodule/main.go:550.36,554.4 3 0 -mymodule/main.go:556.3,557.17 2 1 -mymodule/main.go:557.17,560.4 2 0 -mymodule/main.go:564.50,565.54 1 1 -mymodule/main.go:565.54,566.34 1 1 -mymodule/main.go:566.34,569.4 2 0 -mymodule/main.go:571.3,573.17 3 1 -mymodule/main.go:573.17,576.4 2 0 -mymodule/main.go:578.3,579.17 2 1 -mymodule/main.go:579.17,583.4 3 0 -mymodule/main.go:584.3,593.17 7 1 -mymodule/main.go:593.17,597.4 3 0 -mymodule/main.go:599.3,600.17 2 1 -mymodule/main.go:600.17,604.4 3 0 -mymodule/main.go:605.3,608.17 3 1 -mymodule/main.go:608.17,612.4 3 0 -mymodule/main.go:614.3,616.17 3 1 -mymodule/main.go:616.17,620.4 3 0 -mymodule/main.go:622.3,623.64 2 1 -mymodule/main.go:628.45,629.54 1 1 -mymodule/main.go:629.54,630.34 1 1 -mymodule/main.go:630.34,633.4 2 1 -mymodule/main.go:636.3,638.17 3 1 -mymodule/main.go:638.17,641.4 2 1 -mymodule/main.go:642.3,645.54 2 1 -mymodule/main.go:645.54,648.4 2 1 -mymodule/main.go:651.3,655.17 3 1 -mymodule/main.go:655.17,658.4 2 0 -mymodule/main.go:661.3,662.17 2 1 -mymodule/main.go:662.17,665.4 2 0 -mymodule/main.go:667.3,671.38 4 1 -mymodule/main.go:675.48,676.54 1 1 -mymodule/main.go:676.54,677.34 1 1 -mymodule/main.go:677.34,680.4 2 0 -mymodule/main.go:682.3,684.17 3 1 -mymodule/main.go:684.17,687.4 2 1 -mymodule/main.go:689.3,690.17 2 1 -mymodule/main.go:690.17,693.4 2 0 -mymodule/main.go:694.3,702.17 7 1 -mymodule/main.go:702.17,705.4 2 0 -mymodule/main.go:707.3,708.17 2 1 -mymodule/main.go:708.17,711.4 2 0 -mymodule/main.go:712.3,715.17 3 1 -mymodule/main.go:715.17,718.4 2 0 -mymodule/main.go:720.3,722.17 3 1 -mymodule/main.go:722.17,725.4 2 0 -mymodule/main.go:727.3,728.64 2 1 -mymodule/main.go:732.43,733.54 1 1 -mymodule/main.go:733.54,734.34 1 1 -mymodule/main.go:734.34,737.4 2 0 -mymodule/main.go:739.3,741.17 3 1 -mymodule/main.go:741.17,744.4 2 0 -mymodule/main.go:745.3,747.45 2 1 -mymodule/main.go:747.45,750.4 2 0 -mymodule/main.go:752.3,754.17 3 1 -mymodule/main.go:754.17,757.4 2 0 -mymodule/main.go:759.3,760.17 2 1 -mymodule/main.go:760.17,763.4 2 0 -mymodule/main.go:765.3,768.38 4 1 -mymodule/main.go:773.49,774.54 1 1 -mymodule/main.go:774.54,776.34 1 1 -mymodule/main.go:776.34,779.4 2 0 -mymodule/main.go:782.3,784.17 3 1 -mymodule/main.go:784.17,787.4 2 0 -mymodule/main.go:788.3,791.88 2 1 -mymodule/main.go:791.88,794.4 2 0 -mymodule/main.go:797.3,804.17 3 1 -mymodule/main.go:804.17,807.4 2 0 -mymodule/main.go:810.3,811.17 2 1 -mymodule/main.go:811.17,814.4 2 0 -mymodule/main.go:817.3,818.38 2 1 -mymodule/main.go:823.46,824.54 1 1 -mymodule/main.go:824.54,825.34 1 1 -mymodule/main.go:825.34,828.4 2 0 -mymodule/main.go:830.3,835.17 3 1 -mymodule/main.go:835.17,838.4 2 1 -mymodule/main.go:840.3,840.63 1 1 -mymodule/main.go:840.63,843.4 2 1 -mymodule/main.go:846.3,848.17 3 1 -mymodule/main.go:848.17,851.4 2 1 -mymodule/main.go:852.3,852.17 1 1 -mymodule/main.go:852.17,855.4 2 1 -mymodule/main.go:858.3,859.17 2 1 -mymodule/main.go:859.17,862.4 2 1 -mymodule/main.go:865.3,866.17 2 1 -mymodule/main.go:866.17,869.4 2 1 -mymodule/main.go:871.3,873.62 3 1 -mymodule/main.go:878.54,879.54 1 1 -mymodule/main.go:879.54,880.34 1 1 -mymodule/main.go:880.34,883.4 2 0 -mymodule/main.go:886.3,891.17 3 1 -mymodule/main.go:891.17,894.4 2 0 -mymodule/main.go:897.3,899.23 3 1 -mymodule/main.go:899.23,900.37 1 1 -mymodule/main.go:900.37,902.14 1 0 -mymodule/main.go:902.19,904.14 1 1 -mymodule/main.go:905.13,905.19 1 1 -mymodule/main.go:908.9,908.24 1 1 -mymodule/main.go:908.24,911.10 2 1 -mymodule/main.go:914.3,915.17 2 1 -mymodule/main.go:915.17,918.4 2 1 -mymodule/main.go:921.3,922.17 2 1 -mymodule/main.go:922.17,925.4 2 1 -mymodule/main.go:927.3,928.47 2 1 -mymodule/main.go:932.48,933.54 1 1 -mymodule/main.go:933.54,934.64 1 1 -mymodule/main.go:934.64,937.4 2 1 -mymodule/main.go:939.3,941.17 3 1 -mymodule/main.go:941.17,944.4 2 1 -mymodule/main.go:946.3,948.17 3 1 -mymodule/main.go:948.17,951.4 2 1 -mymodule/main.go:952.3,954.54 2 1 -mymodule/main.go:954.54,957.4 2 1 -mymodule/main.go:959.3,966.17 3 1 -mymodule/main.go:966.17,969.4 2 1 -mymodule/main.go:971.3,972.24 2 1 -mymodule/main.go:972.24,975.4 2 1 -mymodule/main.go:977.3,977.48 1 1 -mymodule/main.go:982.46,983.54 1 1 -mymodule/main.go:983.54,985.64 1 1 -mymodule/main.go:985.64,988.4 2 1 -mymodule/main.go:991.3,993.17 3 1 -mymodule/main.go:993.17,996.4 2 1 -mymodule/main.go:999.3,1007.17 3 1 -mymodule/main.go:1007.17,1010.4 2 1 -mymodule/main.go:1011.3,1018.45 4 1 -mymodule/main.go:1018.45,1021.4 2 1 -mymodule/main.go:1024.3,1032.17 3 1 -mymodule/main.go:1032.17,1035.4 2 1 -mymodule/main.go:1038.3,1039.24 2 1 -mymodule/main.go:1039.24,1042.4 2 1 -mymodule/main.go:1045.3,1045.46 1 1 -mymodule/main.go:1050.52,1051.54 1 1 -mymodule/main.go:1051.54,1053.64 1 1 -mymodule/main.go:1053.64,1056.4 2 1 -mymodule/main.go:1059.3,1061.17 3 1 -mymodule/main.go:1061.17,1064.4 2 1 -mymodule/main.go:1067.3,1069.17 3 1 -mymodule/main.go:1069.17,1072.4 2 1 -mymodule/main.go:1073.3,1080.88 4 1 -mymodule/main.go:1080.88,1083.4 2 1 -mymodule/main.go:1086.3,1094.17 3 1 -mymodule/main.go:1094.17,1097.4 2 1 -mymodule/main.go:1100.3,1101.24 2 1 -mymodule/main.go:1101.24,1104.4 2 1 -mymodule/main.go:1107.3,1107.52 1 1 -mymodule/main.go:1112.48,1113.54 1 0 -mymodule/main.go:1113.54,1115.36 1 0 -mymodule/main.go:1115.36,1118.4 2 0 -mymodule/main.go:1121.3,1123.17 3 0 -mymodule/main.go:1123.17,1126.4 2 0 -mymodule/main.go:1129.3,1138.17 4 0 -mymodule/main.go:1138.17,1141.4 2 0 -mymodule/main.go:1144.3,1144.19 1 0 -mymodule/main.go:1144.19,1147.4 2 0 -mymodule/main.go:1150.3,1157.17 3 0 -mymodule/main.go:1157.17,1160.4 2 0 -mymodule/main.go:1163.3,1164.24 2 0 -mymodule/main.go:1164.24,1167.4 2 0 -mymodule/main.go:1170.3,1170.48 1 0 -mymodule/main.go:1175.46,1176.54 1 0 -mymodule/main.go:1176.54,1178.36 1 0 -mymodule/main.go:1178.36,1181.4 2 0 -mymodule/main.go:1184.3,1186.17 3 0 -mymodule/main.go:1186.17,1189.4 2 0 -mymodule/main.go:1192.3,1201.17 4 0 -mymodule/main.go:1201.17,1204.4 2 0 -mymodule/main.go:1207.3,1216.17 4 0 -mymodule/main.go:1216.17,1219.4 2 0 -mymodule/main.go:1222.3,1229.17 3 0 -mymodule/main.go:1229.17,1232.4 2 0 -mymodule/main.go:1235.3,1236.24 2 0 -mymodule/main.go:1236.24,1239.4 2 0 -mymodule/main.go:1242.3,1242.25 1 0 -mymodule/main.go:1242.25,1250.18 3 0 -mymodule/main.go:1250.18,1253.5 2 0 -mymodule/main.go:1256.3,1256.46 1 0 -mymodule/main.go:1261.52,1262.54 1 0 -mymodule/main.go:1262.54,1264.36 1 0 -mymodule/main.go:1264.36,1267.4 2 0 -mymodule/main.go:1270.3,1272.17 3 0 -mymodule/main.go:1272.17,1275.4 2 0 -mymodule/main.go:1278.3,1285.17 3 0 -mymodule/main.go:1285.17,1288.4 2 0 -mymodule/main.go:1291.3,1292.24 2 0 -mymodule/main.go:1292.24,1295.4 2 0 -mymodule/main.go:1298.3,1298.52 1 0 diff --git a/api/go.mod b/api/go.mod index 8bb3cda..16abe76 100644 --- a/api/go.mod +++ b/api/go.mod @@ -15,5 +15,6 @@ require ( filippo.io/edwards25519 v1.1.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/stretchr/objx v0.5.2 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/api/go.sum b/api/go.sum index 1912f26..65d6f99 100644 --- a/api/go.sum +++ b/api/go.sum @@ -13,6 +13,8 @@ github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwA github.com/kisielk/sqlstruct v0.0.0-20201105191214-5f3e10d3ab46/go.mod h1:yyMNCyc/Ib3bDTKd379tNMpB/7/H5TjM2Y9QJ5THLbE= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= diff --git a/api/main_test.go b/api/main_test.go index 2f8a960..4b57e27 100644 --- a/api/main_test.go +++ b/api/main_test.go @@ -11,9 +11,14 @@ import ( "reflect" "strings" "testing" - "log" "io" + "time" + "log" + "database/sql" + "runtime/debug" + "io/ioutil" + "github.com/stretchr/testify/mock" "github.com/DATA-DOG/go-sqlmock" "github.com/gorilla/mux" "github.com/stretchr/testify/assert" @@ -35,7 +40,186 @@ func setupTestRouter(dbService *TestDBService) *mux.Router { return r } -// Test for GetAllBooks handler +type DBInitializer interface { + InitDB(username, password, hostname, port, dbname string) (*sql.DB, error) +} + +type RouterSetup interface { + SetupRouter(db *sql.DB) *mux.Router +} + +type MockDBInitializer struct { + mock.Mock +} + +func (m *MockDBInitializer) InitDB(username, password, hostname, port, dbname string) (*sql.DB, error) { + args := m.Called(username, password, hostname, port, dbname) + return args.Get(0).(*sql.DB), args.Error(1) +} + +type MockRouterSetup struct { + mock.Mock +} + +func (m *MockRouterSetup) SetupRouter(db *sql.DB) *mux.Router { + args := m.Called(db) + return args.Get(0).(*mux.Router) +} + +type Logger interface { + Println(v ...interface{}) + Fatal(v ...interface{}) +} + +type MockLogger struct { + mock.Mock +} + +func (m *MockLogger) Println(v ...interface{}) { + m.Called(v...) +} + +func (m *MockLogger) Fatal(v ...interface{}) { + m.Called(v...) +} + +func loadTestEnv(filename string) error { + content, err := ioutil.ReadFile(filename) + if err != nil { + return err + } + + lines := strings.Split(string(content), "\n") + for _, line := range lines { + parts := strings.SplitN(line, "=", 2) + if len(parts) == 2 { + os.Setenv(strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1])) + } + } + + return nil +} + +func TestMain(t *testing.T) { + os.Setenv("DB_USER", "testuser") + os.Setenv("DB_PASSWORD", "testpass") + os.Setenv("DB_HOSTNAME", "testhost") + os.Setenv("DB_PORT", "3306") + os.Setenv("DB_NAME", "testdb") + + err := ioutil.WriteFile(".env.test", []byte(` +DB_USER=testuser +DB_PASSWORD=testpass +DB_HOSTNAME=testhost +DB_PORT=3306 +DB_NAME=testdb +`), 0644) + assert.NoError(t, err) + defer os.Remove(".env.test") + + mockDB := new(MockDBInitializer) + mockRouter := new(MockRouterSetup) + mockLogger := new(MockLogger) + + db, err := sql.Open("mysql", "user:password@/dbname") + assert.NoError(t, err) + mockDB.On("InitDB", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(db, nil) + + r := mux.NewRouter() + r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + fmt.Fprintln(w, "Server is running") + }) + mockRouter.On("SetupRouter", mock.Anything).Return(r) + + mockLogger.On("Println", mock.Anything, mock.Anything).Return().Run(func(args mock.Arguments) { + fmt.Printf("Println called with: %v, %v\n", args.Get(0), args.Get(1)) + }) + mockLogger.On("Fatal", mock.Anything, mock.Anything).Maybe().Run(func(args mock.Arguments) { + fmt.Printf("Fatal called with: %v, %v\n", args.Get(0), args.Get(1)) + }) + + started := make(chan bool) + errChan := make(chan error) + + go func() { + defer func() { + if r := recover(); r != nil { + errChan <- fmt.Errorf("Panic in main: %v\nStack trace:\n%s", r, debug.Stack()) + } + }() + + mainWithDependencies(mockDB, mockRouter, mockLogger, loadTestEnv, "8081") + }() + + go func() { + for i := 0; i < 50; i++ { + _, err := http.Get("http://localhost:8081") + if err == nil { + started <- true + return + } + time.Sleep(100 * time.Millisecond) + } + errChan <- fmt.Errorf("Server didn't start within the expected time") + }() + + select { + case <-started: + case err := <-errChan: + t.Fatalf("Error starting server: %v", err) + case <-time.After(6 * time.Second): + t.Fatal("Test timed out") + } + + resp, err := http.Get("http://localhost:8081") + assert.NoError(t, err) + assert.Equal(t, http.StatusOK, resp.StatusCode) + + mockDB.AssertExpectations(t) + mockRouter.AssertExpectations(t) + mockLogger.AssertExpectations(t) +} + +func mainWithDependencies(dbInit DBInitializer, routerSetup RouterSetup, logger Logger, envLoader func(string) error, port string) { + defer func() { + if r := recover(); r != nil { + fmt.Printf("Recovered in mainWithDependencies: %v\nStack trace:\n%s", r, debug.Stack()) + } + }() + + err := envLoader(".env.test") + if err != nil { + logger.Println("No .env file found, continuing with environment variables or defaults") + } + + dbUsername := getEnv("DB_USER", "root") + dbPassword := getEnv("DB_PASSWORD", "password") + dbHostname := getEnv("DB_HOSTNAME", "db") + dbPort := getEnv("DB_PORT", "3306") + dbName := getEnv("DB_NAME", "db") + + db, err := dbInit.InitDB(dbUsername, dbPassword, dbHostname, dbPort, dbName) + if err != nil { + logger.Fatal("Error initializing database:", err) + } + if db == nil { + logger.Fatal("Database connection is nil") + } + defer db.Close() + + logger.Println("Starting our server on port", port) + r := routerSetup.SetupRouter(db) + logger.Println("Started on port", port) + fmt.Println("To close connection CTRL+C :-)") + + err = http.ListenAndServe(":"+port, r) + if err != nil { + logger.Fatal(err) + } +} + +// Test for SearchBooks handler func TestSearchBooks(t *testing.T) { dbService, err := NewTestDBService() if err != nil { @@ -452,7 +636,7 @@ func TestAddAuthorPhoto(t *testing.T) { req := httptest.NewRequest(http.MethodPost, "/authors/1/photo", &buf) req.Header.Set("Content-Type", writer.FormDataContentType()) - expectedPhotoPath := "./upload/1/fullsize.jpg" // Ensure this matches your handler's path + expectedPhotoPath := "./upload/1/fullsize.jpg" dbService.Mock.ExpectExec(`^UPDATE authors SET photo = \? WHERE id = \?$`). WithArgs(expectedPhotoPath, 1). WillReturnResult(sqlmock.NewResult(1, 1)) @@ -712,7 +896,7 @@ func TestAddSubscriber(t *testing.T) { } expected := `{"id":1}` - actual := strings.TrimSpace(rr.Body.String()) // Trim any leading/trailing whitespace or newline characters + actual := strings.TrimSpace(rr.Body.String()) t.Logf("Expected response: '%s'", expected) t.Logf("Actual response: '%s'", actual) @@ -1064,7 +1248,7 @@ func TestUpdateAuthor(t *testing.T) { dbService.Mock.ExpectExec("UPDATE authors"). WithArgs(validAuthor.Lastname, validAuthor.Firstname, validAuthor.Photo, 1). - WillReturnResult(sqlmock.NewResult(1, 0)) // 0 rows affected + WillReturnResult(sqlmock.NewResult(1, 0)) handler := UpdateAuthor(dbService.DB) handler.ServeHTTP(w, req) @@ -1081,7 +1265,7 @@ func TestUpdateAuthor(t *testing.T) { dbService.Mock.ExpectExec("UPDATE authors"). WithArgs(validAuthor.Lastname, validAuthor.Firstname, validAuthor.Photo, 1). - WillReturnResult(sqlmock.NewResult(1, 1)) // 1 row affected + WillReturnResult(sqlmock.NewResult(1, 1)) handler := UpdateAuthor(dbService.DB) handler.ServeHTTP(w, req) @@ -1234,7 +1418,7 @@ func TestUpdateBook(t *testing.T) { dbService.Mock.ExpectExec("UPDATE books"). WithArgs(validBook.Title, validBook.AuthorID, validBook.Photo, validBook.Details, validBook.IsBorrowed, 1). - WillReturnResult(sqlmock.NewResult(1, 1)) // 1 row affected + WillReturnResult(sqlmock.NewResult(1, 1)) handler := UpdateBook(dbService.DB) handler.ServeHTTP(w, req) @@ -1244,14 +1428,14 @@ func TestUpdateBook(t *testing.T) { }) } +// Test for UpdateSubscriber handler func TestUpdateSubscriber(t *testing.T) { - dbService, err := NewTestDBService() // Folosim un serviciu de DB mock + dbService, err := NewTestDBService() if err != nil { t.Fatalf("Unexpected error when opening a stub database connection: %v", err) } defer dbService.DB.Close() - // Setăm logger-ul pentru a nu polua output-ul testelor logger := log.New(io.Discard, "", log.LstdFlags) originalLogger := log.Default() log.SetOutput(logger.Writer()) @@ -1352,7 +1536,7 @@ func TestUpdateSubscriber(t *testing.T) { dbService.Mock.ExpectExec("UPDATE subscribers"). WithArgs(validSubscriber.Lastname, validSubscriber.Firstname, validSubscriber.Email, 1). - WillReturnResult(sqlmock.NewResult(1, 0)) // 0 rows affected + WillReturnResult(sqlmock.NewResult(1, 0)) handler := UpdateSubscriber(dbService.DB) handler.ServeHTTP(w, req) @@ -1377,7 +1561,7 @@ func TestUpdateSubscriber(t *testing.T) { dbService.Mock.ExpectExec("UPDATE subscribers"). WithArgs(validSubscriber.Lastname, validSubscriber.Firstname, validSubscriber.Email, 1). - WillReturnResult(sqlmock.NewResult(1, 1)) // 1 row affected + WillReturnResult(sqlmock.NewResult(1, 1)) handler := UpdateSubscriber(dbService.DB) handler.ServeHTTP(w, req)