github.com/msales/pkg/v3@v3.24.0/httpx/httptest/server.go (about) 1 package httptest 2 3 import ( 4 "net/http" 5 "net/http/httptest" 6 "testing" 7 8 "github.com/ryanuber/go-glob" 9 ) 10 11 const ( 12 // Anything is used where the expectation should not be considered. 13 Anything = "httpx/httptest.Anything" 14 ) 15 16 // Expectation represents an http request expectation. 17 type Expectation struct { 18 method string 19 path string 20 21 fn http.HandlerFunc 22 23 headers []string 24 body []byte 25 status int 26 27 times int 28 } 29 30 // Times sets the number of times the request can be made. 31 func (e *Expectation) Times(times int) *Expectation { 32 e.times = times 33 34 return e 35 } 36 37 // Header sets the HTTP headers that should be returned. 38 func (e *Expectation) Header(k, v string) *Expectation { 39 e.headers = append(e.headers, k, v) 40 41 return e 42 } 43 44 // Handle sets the HTTP handler function to be run on the request. 45 func (e *Expectation) Handle(fn http.HandlerFunc) { 46 e.fn = fn 47 } 48 49 // ReturnsStatus sets the HTTP stats code to return. 50 func (e *Expectation) ReturnsStatus(status int) { 51 e.body = []byte{} 52 e.status = status 53 } 54 55 // Returns sets the HTTP stats and body bytes to return. 56 func (e *Expectation) Returns(status int, body []byte) { 57 e.body = body 58 e.status = status 59 } 60 61 // ReturnsString sets the HTTP stats and body string to return. 62 func (e *Expectation) ReturnsString(status int, body string) { 63 e.body = []byte(body) 64 e.status = status 65 } 66 67 // Server represents a mock http server. 68 type Server struct { 69 t *testing.T 70 srv *httptest.Server 71 72 expect []*Expectation 73 } 74 75 // NewServer creates a new mock http server. 76 func NewServer(t *testing.T) *Server { 77 srv := &Server{ 78 t: t, 79 } 80 srv.srv = httptest.NewServer(http.HandlerFunc(srv.handler)) 81 82 return srv 83 } 84 85 // URL returns the url of the mock server. 86 func (s *Server) URL() string { 87 return s.srv.URL 88 } 89 90 func (s *Server) handler(w http.ResponseWriter, r *http.Request) { 91 method := r.Method 92 path := r.URL.Path 93 for i, exp := range s.expect { 94 if exp.method != method && exp.method != Anything { 95 continue 96 } 97 98 if exp.path != Anything && !glob.Glob(exp.path, path) { 99 continue 100 } 101 102 for i := 0; i < len(exp.headers); i += 2 { 103 w.Header().Add(exp.headers[i], exp.headers[i+1]) 104 } 105 106 if exp.fn != nil { 107 exp.fn(w, r) 108 } else { 109 w.WriteHeader(exp.status) 110 if len(exp.body) > 0 { 111 w.Write(exp.body) 112 } 113 } 114 115 exp.times-- 116 if exp.times == 0 { 117 s.expect = append(s.expect[:i], s.expect[i+1:]...) 118 } 119 return 120 } 121 122 s.t.Errorf("Unexpected call to %s %s", method, path) 123 } 124 125 // On creates an expectation of a request on the server. 126 func (s *Server) On(method, path string) *Expectation { 127 exp := &Expectation{ 128 method: method, 129 path: path, 130 times: -1, 131 status: 200, 132 } 133 s.expect = append(s.expect, exp) 134 135 return exp 136 } 137 138 // AssertExpectations asserts all expectations have been met. 139 func (s *Server) AssertExpectations() { 140 for _, exp := range s.expect { 141 if exp.times > 0 || exp.times == -1 { 142 s.t.Errorf("mock: server: Expected a call to %s %s but got none", exp.method, exp.path) 143 } 144 } 145 } 146 147 // Close closes the server. 148 func (s *Server) Close() { 149 s.srv.Close() 150 }