Skip to content

Commit ec2f939

Browse files
committed
feat: use gin & add call storer
1 parent 449b067 commit ec2f939

File tree

6 files changed

+245
-50
lines changed

6 files changed

+245
-50
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ This library also supports path parameter using `/:pathparam` or `/{pathparam}`.
1515

1616
## Installation
1717

18-
To use go-http-test in your Go projects, you need to have Go (>=1.22) installed and set up. Then, you can install the library using `go get`:
18+
To use go-http-test in your Go projects, you need to have Go (>=1.23) installed and set up. Then, you can install the library using `go get`:
1919

2020
```bash
2121
go get github.com/slzhffktm/go-http-test

go.mod

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,40 @@
11
module github.com/slzhffktm/go-http-test
22

3-
go 1.22
3+
go 1.23
44

55
require (
6+
github.com/gin-gonic/gin v1.10.0
67
github.com/joho/godotenv v1.5.1
7-
github.com/stretchr/testify v1.8.4
8+
github.com/stretchr/testify v1.10.0
89
)
910

1011
require (
12+
github.com/bytedance/sonic v1.11.6 // indirect
13+
github.com/bytedance/sonic/loader v0.1.1 // indirect
14+
github.com/cloudwego/base64x v0.1.4 // indirect
15+
github.com/cloudwego/iasm v0.2.0 // indirect
1116
github.com/davecgh/go-spew v1.1.1 // indirect
17+
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
18+
github.com/gin-contrib/sse v0.1.0 // indirect
19+
github.com/go-playground/locales v0.14.1 // indirect
20+
github.com/go-playground/universal-translator v0.18.1 // indirect
21+
github.com/go-playground/validator/v10 v10.20.0 // indirect
22+
github.com/goccy/go-json v0.10.2 // indirect
23+
github.com/json-iterator/go v1.1.12 // indirect
24+
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
25+
github.com/leodido/go-urn v1.4.0 // indirect
26+
github.com/mattn/go-isatty v0.0.20 // indirect
27+
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
28+
github.com/modern-go/reflect2 v1.0.2 // indirect
29+
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
1230
github.com/pmezard/go-difflib v1.0.0 // indirect
31+
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
32+
github.com/ugorji/go/codec v1.2.12 // indirect
33+
golang.org/x/arch v0.8.0 // indirect
34+
golang.org/x/crypto v0.23.0 // indirect
35+
golang.org/x/net v0.25.0 // indirect
36+
golang.org/x/sys v0.20.0 // indirect
37+
golang.org/x/text v0.15.0 // indirect
38+
google.golang.org/protobuf v1.34.1 // indirect
1339
gopkg.in/yaml.v3 v3.0.1 // indirect
1440
)

go.sum

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,92 @@
1+
github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
2+
github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
3+
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
4+
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
5+
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
6+
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
7+
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
8+
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
9+
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
110
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
211
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
12+
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
13+
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
14+
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
15+
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
16+
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
17+
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
18+
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
19+
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
20+
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
21+
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
22+
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
23+
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
24+
github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8=
25+
github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
26+
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
27+
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
28+
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
29+
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
30+
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
331
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
432
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
33+
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
34+
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
35+
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
36+
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
37+
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
38+
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
39+
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
40+
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
41+
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
42+
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
43+
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
44+
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
45+
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
46+
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
47+
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
48+
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
49+
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
550
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
651
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
7-
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
52+
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
53+
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
54+
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
55+
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
56+
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
57+
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
58+
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
59+
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
60+
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
861
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
62+
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
63+
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
64+
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
65+
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
66+
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
67+
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
68+
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
69+
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
70+
golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
71+
golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
72+
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
73+
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
74+
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
75+
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
76+
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
77+
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
78+
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
79+
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
80+
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
81+
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
82+
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
83+
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
84+
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
85+
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
986
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
1087
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
88+
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
1189
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
1290
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
91+
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
92+
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=

httptest.go

Lines changed: 103 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,27 @@
11
package httptest
22

33
import (
4+
"bytes"
45
"errors"
56
"fmt"
7+
"io"
68
"net"
79
"net/http"
8-
"regexp"
10+
"net/url"
911
"sync"
12+
13+
"github.com/gin-gonic/gin"
1014
)
1115

1216
// Server is a mock http server for testing.
1317
type Server struct {
1418
httpServer *http.Server
15-
// calls store map[method][path]count
16-
calls map[string]map[string]int
19+
engine *gin.Engine
20+
// nCalls store map[method][path]count
21+
nCalls map[string]map[string]int
1722
// routes store map[method][path]handler
1823
routes map[string]map[string]ServerHandlerFunc
24+
calls map[string]map[string][]RequestMade
1925

2026
mu sync.Mutex
2127
}
@@ -25,6 +31,13 @@ type Request struct {
2531
Params Params
2632
}
2733

34+
type RequestMade struct {
35+
Body []byte
36+
Headers http.Header
37+
Query url.Values
38+
Params map[string]string
39+
}
40+
2841
// ServerHandlerFunc is the interface of the handler function.
2942
type ServerHandlerFunc func(w ResponseWriter, r *Request)
3043

@@ -35,20 +48,28 @@ type ServerConfig struct {
3548
// NewServer creates and starts new http test server.
3649
// address is the address to listen on, e.g. "localhost:3001".
3750
func NewServer(address string, config ServerConfig) (*Server, error) {
51+
// Set gin to release mode to avoid unnecessary logs.
52+
gin.SetMode(gin.ReleaseMode)
53+
54+
// Start listener first to make sure the address is available.
3855
l, err := net.Listen("tcp", address)
3956
if err != nil {
40-
panic(err)
57+
return nil, fmt.Errorf("net.Listen: %w", err)
4158
}
4259

60+
r := gin.Default()
61+
4362
httpServer := &http.Server{
4463
Addr: address,
45-
Handler: http.NewServeMux(),
64+
Handler: r.Handler(),
4665
}
4766

4867
server := &Server{
68+
engine: r,
4969
httpServer: httpServer,
50-
calls: map[string]map[string]int{},
70+
nCalls: map[string]map[string]int{},
5171
routes: map[string]map[string]ServerHandlerFunc{},
72+
calls: map[string]map[string][]RequestMade{},
5273
}
5374

5475
go func() {
@@ -65,24 +86,43 @@ func (s *Server) Close() error {
6586
return s.httpServer.Close()
6687
}
6788

68-
// GetNCalls returns the number of calls for a path.
89+
// GetNCalls returns the number of nCalls for a path.
6990
func (s *Server) GetNCalls(method, path string) int {
70-
calls, ok := s.calls[method][path]
91+
calls, ok := s.nCalls[method][path]
7192
if !ok {
7293
return 0
7394
}
7495

7596
return calls
7697
}
7798

78-
// ResetNCalls resets the number of calls for all paths.
99+
// ResetNCalls resets the number of nCalls for all paths.
79100
func (s *Server) ResetNCalls() {
80101
s.mu.Lock()
81102
defer s.mu.Unlock()
82103

104+
for path := range s.nCalls {
105+
for method := range s.nCalls[path] {
106+
s.nCalls[path][method] = 0
107+
}
108+
}
109+
}
110+
111+
// GetCalls returns the calls for a path.
112+
func (s *Server) GetCalls(method, path string) []RequestMade {
113+
return s.calls[method][path]
114+
}
115+
116+
// ResetCalls resets the calls & nCalls for all paths.
117+
// It does not reset the handlers.
118+
func (s *Server) ResetCalls() {
119+
s.mu.Lock()
120+
defer s.mu.Unlock()
121+
122+
s.ResetNCalls()
83123
for path := range s.calls {
84124
for method := range s.calls[path] {
85-
s.calls[path][method] = 0
125+
s.calls[path][method] = []RequestMade{}
86126
}
87127
}
88128
}
@@ -93,69 +133,92 @@ func (s *Server) RegisterHandler(method string, path string, handler ServerHandl
93133
s.mu.Lock()
94134
defer s.mu.Unlock()
95135

96-
if s.calls[method] == nil {
97-
s.calls[method] = map[string]int{}
136+
if s.nCalls[method] == nil {
137+
s.nCalls[method] = map[string]int{}
98138
}
99139
if s.routes[method] == nil {
100140
s.routes[method] = map[string]ServerHandlerFunc{}
101141
}
142+
if s.calls[method] == nil {
143+
s.calls[method] = map[string][]RequestMade{}
144+
}
102145

103146
if s.routes[method] != nil && s.routes[method][path] != nil {
104147
// Regenerate the handler and re-register all handlers.
105-
serveMux := http.NewServeMux()
148+
s.engine = gin.Default()
106149
for m, p := range s.routes {
107150
for k, v := range p {
151+
// Skip same one, we'll register it below.
108152
if m == method && k == path {
109153
continue
110154
}
111-
serveMux.HandleFunc(k, func(w http.ResponseWriter, r *http.Request) {
112-
s.IncrNCalls(m, k)
113-
v(ResponseWriter{w: w}, &Request{Request: r, Params: Params{request: r}})
155+
s.engine.Handle(m, k, func(c *gin.Context) {
156+
s.incrNCalls(m, k)
157+
s.storeCall(m, k, c)
158+
v(ResponseWriter{w: c.Writer}, &Request{Request: c.Request, Params: Params{ginContext: c}})
114159
})
115160
}
116161
}
117-
s.httpServer.Handler = serveMux
162+
s.httpServer.Handler = s.engine.Handler()
118163
}
119164
s.routes[method][path] = handler
120165

121-
serveMux := s.httpServer.Handler.(*http.ServeMux)
122-
serveMux.HandleFunc(s.combinePath(method, path), func(w http.ResponseWriter, r *http.Request) {
123-
s.IncrNCalls(method, path)
124-
handler(ResponseWriter{w: w}, &Request{Request: r, Params: Params{request: r}})
166+
s.engine.Handle(method, path, func(c *gin.Context) {
167+
s.incrNCalls(method, path)
168+
s.storeCall(method, path, c)
169+
handler(ResponseWriter{w: c.Writer}, &Request{Request: c.Request, Params: Params{ginContext: c}})
125170
})
126171

127-
s.httpServer.Handler = serveMux
172+
s.httpServer.Handler = s.engine.Handler()
128173
}
129174

130-
// IncrNCalls increments the number of calls for a path.
131-
func (s *Server) IncrNCalls(method, path string) {
175+
// incrNCalls increments the number of nCalls for a path.
176+
func (s *Server) incrNCalls(method, path string) {
132177
s.mu.Lock()
133178
defer s.mu.Unlock()
134179

135-
s.calls[method][path]++
180+
s.nCalls[method][path]++
136181
}
137182

138-
// ResetAll resets all the calls and handlers.
139-
func (s *Server) ResetAll() {
183+
// storeCall stores the call for a path.
184+
func (s *Server) storeCall(method, path string, c *gin.Context) {
140185
s.mu.Lock()
141186
defer s.mu.Unlock()
142187

143-
s.httpServer.Handler = http.NewServeMux()
144-
s.calls = map[string]map[string]int{}
145-
s.routes = map[string]map[string]ServerHandlerFunc{}
188+
// If body is not empty, read it into byte.
189+
var body []byte
190+
if c.Request.Body != nil {
191+
body, _ = io.ReadAll(c.Request.Body)
192+
// Restore the body.
193+
c.Request.Body = io.NopCloser(bytes.NewBuffer(body))
194+
}
195+
196+
s.calls[method][path] = append(s.calls[method][path], RequestMade{
197+
Body: body,
198+
Headers: c.Request.Header,
199+
Query: c.Request.URL.Query(),
200+
Params: s.getAllParams(c),
201+
})
146202
}
147203

148-
// combinePath combines method and path & converts the path.
149-
// Example: combinePath(GET, /path/:param) -> GET /path/{param}
150-
func (s *Server) combinePath(method, path string) string {
151-
return fmt.Sprintf("%s %s", method, s.convertPathParams(path))
204+
func (s *Server) getAllParams(c *gin.Context) map[string]string {
205+
params := make(map[string]string)
206+
207+
for _, param := range c.Params {
208+
params[param.Key] = param.Value
209+
}
210+
211+
return params
152212
}
153213

154-
// convertPathParams converts from "/path/:param" to "/path/{param}" to comply with the standard library.
155-
func (s *Server) convertPathParams(input string) string {
156-
pattern := `:([^/]+)`
157-
re := regexp.MustCompile(pattern)
158-
converted := re.ReplaceAllString(input, "{$1}")
214+
// ResetAll resets all the nCalls, handlers, and calls.
215+
func (s *Server) ResetAll() {
216+
s.mu.Lock()
217+
defer s.mu.Unlock()
159218

160-
return converted
219+
s.engine = gin.Default()
220+
s.httpServer.Handler = s.engine.Handler()
221+
s.nCalls = map[string]map[string]int{}
222+
s.routes = map[string]map[string]ServerHandlerFunc{}
223+
s.calls = map[string]map[string][]RequestMade{}
161224
}

0 commit comments

Comments
 (0)