Skip to content

Commit a62b874

Browse files
authored
Merge pull request #119 from jarcoal/unregister
feat: registering a nil responder unregisters it
2 parents 5115a49 + b1c767b commit a62b874

File tree

2 files changed

+121
-15
lines changed

2 files changed

+121
-15
lines changed

transport.go

+76-14
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,14 @@ func (m *MockTransport) checkMethod(method string) {
364364
// GetCallCountInfo(). As 2 regexps can match the same URL, the regexp
365365
// responders are tested in the order they are registered. Registering
366366
// an already existing regexp responder (same method & same regexp
367-
// string) replaces its responder but does not change its position.
367+
// string) replaces its responder, but does not change its position.
368+
//
369+
// Registering an already existing responder resets the corresponding
370+
// statistics as returned by GetCallCountInfo().
371+
//
372+
// Registering a nil Responder removes the existing one and the
373+
// corresponding statistics as returned by GetCallCountInfo(). It does
374+
// nothing if it does not already exist.
368375
//
369376
// See RegisterRegexpResponder() to directly pass a *regexp.Regexp.
370377
//
@@ -410,31 +417,49 @@ func (m *MockTransport) RegisterResponder(method, url string, responder Responde
410417
}
411418

412419
m.mu.Lock()
413-
m.responders[key] = responder
414-
m.callCountInfo[key] = 0
420+
if responder == nil {
421+
delete(m.responders, key)
422+
delete(m.callCountInfo, key)
423+
} else {
424+
m.responders[key] = responder
425+
m.callCountInfo[key] = 0
426+
}
415427
m.mu.Unlock()
416428
}
417429

418-
func (m *MockTransport) registerRegexpResponder(regexpResponder regexpResponder) {
430+
func (m *MockTransport) registerRegexpResponder(rxResp regexpResponder) {
419431
m.mu.Lock()
420432
defer m.mu.Unlock()
421433

422434
found:
423435
for {
424436
for i, rr := range m.regexpResponders {
425-
if rr.method == regexpResponder.method && rr.origRx == regexpResponder.origRx {
426-
m.regexpResponders[i] = regexpResponder
437+
if rr.method == rxResp.method && rr.origRx == rxResp.origRx {
438+
if rxResp.responder == nil {
439+
copy(m.regexpResponders[:i], m.regexpResponders[i+1:])
440+
m.regexpResponders[len(m.regexpResponders)-1] = regexpResponder{}
441+
m.regexpResponders = m.regexpResponders[:len(m.regexpResponders)-1]
442+
} else {
443+
m.regexpResponders[i] = rxResp
444+
}
427445
break found
428446
}
429447
}
430-
m.regexpResponders = append(m.regexpResponders, regexpResponder)
448+
if rxResp.responder != nil {
449+
m.regexpResponders = append(m.regexpResponders, rxResp)
450+
}
431451
break // nolint: staticcheck
432452
}
433453

434-
m.callCountInfo[internal.RouteKey{
435-
Method: regexpResponder.method,
436-
URL: regexpResponder.origRx,
437-
}] = 0
454+
key := internal.RouteKey{
455+
Method: rxResp.method,
456+
URL: rxResp.origRx,
457+
}
458+
if rxResp.responder == nil {
459+
delete(m.callCountInfo, key)
460+
} else {
461+
m.callCountInfo[key] = 0
462+
}
438463
}
439464

440465
// RegisterRegexpResponder adds a new responder, associated with a given
@@ -446,7 +471,12 @@ found:
446471
// As 2 regexps can match the same URL, the regexp responders are
447472
// tested in the order they are registered. Registering an already
448473
// existing regexp responder (same method & same regexp string)
449-
// replaces its responder but does not change its position.
474+
// replaces its responder, but does not change its position, and
475+
// resets the corresponding statistics as returned by GetCallCountInfo().
476+
//
477+
// Registering a nil Responder removes the existing one and the
478+
// corresponding statistics as returned by GetCallCountInfo(). It does
479+
// nothing if it does not already exist.
450480
//
451481
// A "=~" prefix is added to the stringified regexp in the statistics
452482
// returned by GetCallCountInfo().
@@ -483,6 +513,13 @@ func (m *MockTransport) RegisterRegexpResponder(method string, urlRegexp *regexp
483513
// Unlike RegisterResponder, path cannot be prefixed by "=~" to say it
484514
// is a regexp. If it is, a panic occurs.
485515
//
516+
// Registering an already existing responder resets the corresponding
517+
// statistics as returned by GetCallCountInfo().
518+
//
519+
// Registering a nil Responder removes the existing one and the
520+
// corresponding statistics as returned by GetCallCountInfo(). It does
521+
// nothing if it does not already exist.
522+
//
486523
// If method is a lower-cased version of CONNECT, DELETE, GET, HEAD,
487524
// OPTIONS, POST, PUT or TRACE, a panics occurs to notice the possible
488525
// mistake. This panic can be disabled by setting m.DontCheckMethod to
@@ -581,6 +618,9 @@ func sortedQuery(m url.Values) string {
581618
// at /go/src/testing/testing.go:865
582619
// testing.tRunner()
583620
// at /go/src/runtime/asm_amd64.s:1337
621+
//
622+
// If responder is passed as nil, the default behavior
623+
// (httpmock.ConnectionFailure) is re-enabled.
584624
func (m *MockTransport) RegisterNoResponder(responder Responder) {
585625
m.mu.Lock()
586626
m.noResponder = responder
@@ -812,7 +852,14 @@ func DeactivateAndReset() {
812852
// GetCallCountInfo(). As 2 regexps can match the same URL, the regexp
813853
// responders are tested in the order they are registered. Registering
814854
// an already existing regexp responder (same method & same regexp
815-
// string) replaces its responder but does not change its position.
855+
// string) replaces its responder, but does not change its position.
856+
//
857+
// Registering an already existing responder resets the corresponding
858+
// statistics as returned by GetCallCountInfo().
859+
//
860+
// Registering a nil Responder removes the existing one and the
861+
// corresponding statistics as returned by GetCallCountInfo(). It does
862+
// nothing if it does not already exist.
816863
//
817864
// See RegisterRegexpResponder() to directly pass a *regexp.Regexp.
818865
//
@@ -852,7 +899,12 @@ func RegisterResponder(method, url string, responder Responder) {
852899
// As 2 regexps can match the same URL, the regexp responders are
853900
// tested in the order they are registered. Registering an already
854901
// existing regexp responder (same method & same regexp string)
855-
// replaces its responder but does not change its position.
902+
// replaces its responder, but does not change its position, and
903+
// resets the corresponding statistics as returned by GetCallCountInfo().
904+
//
905+
// Registering a nil Responder removes the existing one and the
906+
// corresponding statistics as returned by GetCallCountInfo(). It does
907+
// nothing if it does not already exist.
856908
//
857909
// A "=~" prefix is added to the stringified regexp in the statistics
858910
// returned by GetCallCountInfo().
@@ -879,6 +931,16 @@ func RegisterRegexpResponder(method string, urlRegexp *regexp.Regexp, responder
879931
// If the query type is not recognized or the string cannot be parsed
880932
// using net/url.ParseQuery, a panic() occurs.
881933
//
934+
// Unlike RegisterResponder, path cannot be prefixed by "=~" to say it
935+
// is a regexp. If it is, a panic occurs.
936+
//
937+
// Registering an already existing responder resets the corresponding
938+
// statistics as returned by GetCallCountInfo().
939+
//
940+
// Registering a nil Responder removes the existing one and the
941+
// corresponding statistics as returned by GetCallCountInfo(). It does
942+
// nothing if it does not already exist.
943+
//
882944
// Example using a net/url.Values:
883945
// func TestFetchArticles(t *testing.T) {
884946
// httpmock.Activate()

transport_test.go

+45-1
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ func TestMockTransportReset(t *testing.T) {
153153
t.Fatal("expected no responders at this point")
154154
}
155155

156-
RegisterResponder("GET", testURL, nil)
156+
RegisterResponder("GET", testURL, NewStringResponder(200, "hey"))
157157

158158
if DefaultTransport.NumResponders() != 1 {
159159
t.Fatal("expected one responder")
@@ -687,9 +687,25 @@ func TestMockTransportCallCountZero(t *testing.T) {
687687
if !reflect.DeepEqual(info, expectedInfo) {
688688
t.Fatalf("did not correctly reset the call count info. expected it to be \n %+v\n but it was \n %+v", expectedInfo, info)
689689
}
690+
691+
// Unregister each responder
692+
RegisterResponder("GET", url, nil)
693+
RegisterResponder("POST", "=~gitlab", nil)
694+
695+
info = GetCallCountInfo()
696+
expectedInfo = map[string]int{
697+
// this one remains as it is not directly related to a registered
698+
// responder but a consequence of a regexp match
699+
"POST " + url2: 0,
700+
}
701+
if !reflect.DeepEqual(info, expectedInfo) {
702+
t.Fatalf("did not correctly reset the call count info. expected it to be \n %+v\n but it was \n %+v", expectedInfo, info)
703+
}
690704
}
691705

692706
func TestRegisterResponderWithQuery(t *testing.T) {
707+
Reset()
708+
693709
// Just in case a panic occurs
694710
defer DeactivateAndReset()
695711

@@ -768,6 +784,34 @@ func TestRegisterResponderWithQuery(t *testing.T) {
768784
assertBody(t, resp, body)
769785
}
770786

787+
if info := GetCallCountInfo(); len(info) != 1 {
788+
t.Fatalf("%s: len(GetCallCountInfo()) should be 1 but contains %+v", testURLPath, info)
789+
}
790+
791+
// Remove...
792+
RegisterResponderWithQuery("GET", testURLPath, query, nil)
793+
if info := GetCallCountInfo(); len(info) != 0 {
794+
t.Fatalf("did not correctly reset the call count info, it still contains %+v", info)
795+
}
796+
797+
for _, url := range test.URLs {
798+
t.Logf("query=%v URL=%s", query, url)
799+
800+
req, err := http.NewRequest("GET", url, nil)
801+
if err != nil {
802+
t.Fatal(err)
803+
}
804+
805+
_, err = client.Do(req)
806+
if err == nil {
807+
t.Fatalf("No error occurred for %s", url)
808+
}
809+
810+
if !strings.HasSuffix(err.Error(), "no responder found") {
811+
t.Errorf("Not expected error suffix: %s", err)
812+
}
813+
}
814+
771815
DeactivateAndReset()
772816
}
773817
}

0 commit comments

Comments
 (0)