github.com/chelnak/go-gh@v0.0.2/internal/httpmock/registry.go (about) 1 package httpmock 2 3 import ( 4 "fmt" 5 "net/http" 6 "sync" 7 "testing" 8 ) 9 10 type Registry struct { 11 mu sync.Mutex 12 stubs []*Stub 13 Requests []*http.Request 14 } 15 16 func NewRegistry(t *testing.T) *Registry { 17 reg := Registry{} 18 t.Cleanup(func() { reg.Verify(t) }) 19 return ® 20 } 21 22 func (r *Registry) Register(m Matcher, resp Responder) { 23 r.stubs = append(r.stubs, &Stub{ 24 Matcher: m, 25 Responder: resp, 26 }) 27 } 28 29 type Testing interface { 30 Errorf(string, ...interface{}) 31 Helper() 32 } 33 34 func (r *Registry) Verify(t Testing) { 35 n := 0 36 for _, s := range r.stubs { 37 if !s.matched { 38 n++ 39 } 40 } 41 if n > 0 { 42 t.Helper() 43 // NOTE: Stubs offer no useful reflection, so we can't print details 44 // about dead stubs and what they were trying to match. 45 t.Errorf("%d unmatched HTTP stubs", n) 46 } 47 } 48 49 // Registry satisfies http.RoundTripper interface. 50 func (r *Registry) RoundTrip(req *http.Request) (*http.Response, error) { 51 var stub *Stub 52 53 r.mu.Lock() 54 for _, s := range r.stubs { 55 if s.matched || !s.Matcher(req) { 56 continue 57 } 58 if stub != nil { 59 r.mu.Unlock() 60 return nil, fmt.Errorf("more than 1 stub matched %v", req) 61 } 62 stub = s 63 } 64 if stub != nil { 65 stub.matched = true 66 } 67 68 if stub == nil { 69 r.mu.Unlock() 70 return nil, fmt.Errorf("no registered stubs matched %v", req) 71 } 72 73 r.Requests = append(r.Requests, req) 74 r.mu.Unlock() 75 76 return stub.Responder(req) 77 }