diff --git a/gock_test.go b/gock_test.go
index 4254be1..7430d83 100644
--- a/gock_test.go
+++ b/gock_test.go
@@ -98,6 +98,23 @@ func TestMockBodyMatchJSON(t *testing.T) {
st.Expect(t, string(body)[:13], `{"bar":"foo"}`)
}
+func TestMockBodyMatchMultiple(t *testing.T) {
+ defer after()
+ New("http://foo.com").
+ Post("/bar").
+ JSON(map[string]string{"foo": "bar", "baz": "foo"}).
+ BodyString("baz").
+ BodyString("bar").
+ Reply(201).
+ BodyString("intercepted")
+
+ res, err := http.Post("http://foo.com/bar", "application/json", bytes.NewBuffer([]byte(`{"foo":"bar", "baz":"foo"}`)))
+ st.Expect(t, err, nil)
+ st.Expect(t, res.StatusCode, 201)
+ body, _ := ioutil.ReadAll(res.Body)
+ st.Expect(t, string(body), `intercepted`)
+}
+
func TestMockBodyCannotMatchJSON(t *testing.T) {
defer after()
New("http://foo.com").
diff --git a/matchers.go b/matchers.go
index ca0898a..25f338d 100644
--- a/matchers.go
+++ b/matchers.go
@@ -112,76 +112,80 @@ func MatchQueryParams(req *http.Request, ereq *Request) (bool, error) {
// MatchBody tries to match the request body.
// TODO: not too smart now, needs several improvements.
func MatchBody(req *http.Request, ereq *Request) (bool, error) {
- // If match body is empty, just continue
- if req.Method == "HEAD" || len(ereq.BodyBuffer) == 0 {
- return true, nil
- }
-
- // Only can match certain MIME body types
- if !supportedType(req) {
- return false, nil
- }
+ for _, bodyBuffer := range ereq.BodyMatchers {
+ // If match body is empty, just continue
+ if req.Method == "HEAD" || len(bodyBuffer) == 0 {
+ continue
+ }
- // Can only match certain compression schemes
- if !supportedCompressionScheme(req) {
- return false, nil
- }
+ // Only can match certain MIME body types
+ if !supportedType(req) {
+ return false, nil
+ }
- // Create a reader for the body depending on compression type
- bodyReader := req.Body
- if ereq.CompressionScheme != "" {
- if ereq.CompressionScheme != req.Header.Get("Content-Encoding") {
+ // Can only match certain compression schemes
+ if !supportedCompressionScheme(req) {
return false, nil
}
- compressedBodyReader, err := compressionReader(req.Body, ereq.CompressionScheme)
+
+ // Create a reader for the body depending on compression type
+ bodyReader := req.Body
+ if ereq.CompressionScheme != "" {
+ if ereq.CompressionScheme != req.Header.Get("Content-Encoding") {
+ return false, nil
+ }
+ compressedBodyReader, err := compressionReader(req.Body, ereq.CompressionScheme)
+ if err != nil {
+ return false, err
+ }
+ bodyReader = compressedBodyReader
+ }
+
+ // Read the whole request body
+ body, err := ioutil.ReadAll(bodyReader)
if err != nil {
return false, err
}
- bodyReader = compressedBodyReader
- }
- // Read the whole request body
- body, err := ioutil.ReadAll(bodyReader)
- if err != nil {
- return false, err
- }
+ // Restore body reader stream
+ req.Body = createReadCloser(body)
- // Restore body reader stream
- req.Body = createReadCloser(body)
+ // If empty, ignore the match
+ if len(body) == 0 && len(bodyBuffer) != 0 {
+ return false, nil
+ }
- // If empty, ignore the match
- if len(body) == 0 && len(ereq.BodyBuffer) != 0 {
- return false, nil
- }
+ // Match body by atomic string comparison
+ bodyStr := castToString(body)
+ matchStr := castToString(bodyBuffer)
+ if bodyStr == matchStr {
+ continue
+ }
- // Match body by atomic string comparison
- bodyStr := castToString(body)
- matchStr := castToString(ereq.BodyBuffer)
- if bodyStr == matchStr {
- return true, nil
- }
+ // Match request body by regexp
+ match, _ := regexp.MatchString(matchStr, bodyStr)
+ if match == true {
+ continue
+ }
- // Match request body by regexp
- match, _ := regexp.MatchString(matchStr, bodyStr)
- if match == true {
- return true, nil
- }
+ // todo - add conditional do only perform the conversion of body bytes
+ // representation of JSON to a map and then compare them for equality.
- // todo - add conditional do only perform the conversion of body bytes
- // representation of JSON to a map and then compare them for equality.
+ // Check if the key + value pairs match
+ var bodyMap map[string]interface{}
+ var matchMap map[string]interface{}
- // Check if the key + value pairs match
- var bodyMap map[string]interface{}
- var matchMap map[string]interface{}
+ // Ensure that both byte bodies that that should be JSON can be converted to maps.
+ umErr := json.Unmarshal(body, &bodyMap)
+ umErr2 := json.Unmarshal(bodyBuffer, &matchMap)
+ if umErr == nil && umErr2 == nil && reflect.DeepEqual(bodyMap, matchMap) {
+ continue
+ }
- // Ensure that both byte bodies that that should be JSON can be converted to maps.
- umErr := json.Unmarshal(body, &bodyMap)
- umErr2 := json.Unmarshal(ereq.BodyBuffer, &matchMap)
- if umErr == nil && umErr2 == nil && reflect.DeepEqual(bodyMap, matchMap) {
- return true, nil
+ return false, nil
}
- return false, nil
+ return true, nil
}
func supportedType(req *http.Request) bool {
diff --git a/matchers_test.go b/matchers_test.go
index 23d395f..808dca7 100644
--- a/matchers_test.go
+++ b/matchers_test.go
@@ -177,7 +177,7 @@ func TestMatchBody(t *testing.T) {
for _, test := range cases {
req := &http.Request{Body: createReadCloser([]byte(test.body))}
- ereq := &Request{BodyBuffer: []byte(test.value)}
+ ereq := &Request{BodyMatchers: [][]byte{[]byte(test.value)}}
matches, err := MatchBody(req, ereq)
st.Expect(t, err, nil)
st.Expect(t, matches, test.matches)
diff --git a/request.go b/request.go
index cee9a55..6c3badf 100644
--- a/request.go
+++ b/request.go
@@ -47,8 +47,8 @@ type Request struct {
// Cookies stores the Request HTTP cookies values to match.
Cookies []*http.Cookie
- // BodyBuffer stores the body data to match.
- BodyBuffer []byte
+ // BodyMatchers stores the body data to match.
+ BodyMatchers [][]byte
// Mappers stores the request functions mappers used for matching.
Mappers []MapRequestFunc
@@ -125,19 +125,23 @@ func (r *Request) method(method, path string) *Request {
// Body defines the body data to match based on a io.Reader interface.
func (r *Request) Body(body io.Reader) *Request {
- r.BodyBuffer, r.Error = ioutil.ReadAll(body)
+ var bodyBuffer []byte
+ bodyBuffer, r.Error = ioutil.ReadAll(body)
+ r.BodyMatchers = append(r.BodyMatchers, bodyBuffer)
return r
}
// BodyString defines the body to match based on a given string.
func (r *Request) BodyString(body string) *Request {
- r.BodyBuffer = []byte(body)
+ r.BodyMatchers = append(r.BodyMatchers, []byte(body))
return r
}
// File defines the body to match based on the given file path string.
func (r *Request) File(path string) *Request {
- r.BodyBuffer, r.Error = ioutil.ReadFile(path)
+ var bodyBuffer []byte
+ bodyBuffer, r.Error = ioutil.ReadFile(path)
+ r.BodyMatchers = append(r.BodyMatchers, bodyBuffer)
return r
}
@@ -154,7 +158,10 @@ func (r *Request) JSON(data interface{}) *Request {
if r.Header.Get("Content-Type") == "" {
r.Header.Set("Content-Type", "application/json")
}
- r.BodyBuffer, r.Error = readAndDecode(data, "json")
+
+ var bodyBuffer []byte
+ bodyBuffer, r.Error = readAndDecode(data, "json")
+ r.BodyMatchers = append(r.BodyMatchers, bodyBuffer)
return r
}
@@ -163,7 +170,10 @@ func (r *Request) XML(data interface{}) *Request {
if r.Header.Get("Content-Type") == "" {
r.Header.Set("Content-Type", "application/xml")
}
- r.BodyBuffer, r.Error = readAndDecode(data, "xml")
+
+ var bodyBuffer []byte
+ bodyBuffer, r.Error = readAndDecode(data, "xml")
+ r.BodyMatchers = append(r.BodyMatchers, bodyBuffer)
return r
}
diff --git a/request_test.go b/request_test.go
index 666c892..7f6e2f5 100644
--- a/request_test.go
+++ b/request_test.go
@@ -38,25 +38,25 @@ func TestRequestPath(t *testing.T) {
func TestRequestBody(t *testing.T) {
req := NewRequest()
req.Body(bytes.NewBuffer([]byte("foo bar")))
- st.Expect(t, string(req.BodyBuffer), "foo bar")
+ st.Expect(t, string(req.BodyMatchers[0]), "foo bar")
}
func TestRequestBodyString(t *testing.T) {
req := NewRequest()
req.BodyString("foo bar")
- st.Expect(t, string(req.BodyBuffer), "foo bar")
+ st.Expect(t, string(req.BodyMatchers[0]), "foo bar")
}
func TestRequestFile(t *testing.T) {
req := NewRequest()
req.File("version.go")
- st.Expect(t, string(req.BodyBuffer)[:12], "package gock")
+ st.Expect(t, string(req.BodyMatchers[0])[:12], "package gock")
}
func TestRequestJSON(t *testing.T) {
req := NewRequest()
req.JSON(map[string]string{"foo": "bar"})
- st.Expect(t, string(req.BodyBuffer)[:13], `{"foo":"bar"}`)
+ st.Expect(t, string(req.BodyMatchers[0])[:13], `{"foo":"bar"}`)
st.Expect(t, req.Header.Get("Content-Type"), "application/json")
}
@@ -66,10 +66,25 @@ func TestRequestXML(t *testing.T) {
Data string `xml:"data"`
}
req.XML(xml{Data: "foo"})
- st.Expect(t, string(req.BodyBuffer), `foo`)
+ st.Expect(t, string(req.BodyMatchers[0]), `foo`)
st.Expect(t, req.Header.Get("Content-Type"), "application/xml")
}
+func TestRequestMultipleMatchers(t *testing.T) {
+ // Body()
+ req := NewRequest()
+ req.Body(bytes.NewBuffer([]byte("foo bar")))
+ // BodyString()
+ req.BodyString("foo bar")
+ // JSON()
+ req.JSON(map[string]string{"foo": "bar"})
+
+ st.Expect(t, string(req.BodyMatchers[0]), "foo bar")
+ st.Expect(t, string(req.BodyMatchers[1]), "foo bar")
+ st.Expect(t, string(req.BodyMatchers[2])[:13], `{"foo":"bar"}`)
+ st.Expect(t, req.Header.Get("Content-Type"), "application/json")
+}
+
func TestRequestMatchType(t *testing.T) {
req := NewRequest()
req.MatchType("json")