From 80a1e220978c6dd8809126f1d2ca2b77784d46d1 Mon Sep 17 00:00:00 2001 From: steinfletcher Date: Sun, 12 May 2019 20:57:31 +0100 Subject: [PATCH] add mock header present/not present matchers --- mocks.go | 48 ++++++++++++++++++++++ mocks_test.go | 111 ++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 138 insertions(+), 21 deletions(-) diff --git a/mocks.go b/mocks.go index 8288f72..3dbbaf8 100644 --- a/mocks.go +++ b/mocks.go @@ -200,8 +200,11 @@ type MockRequest struct { url *url.URL method string headers map[string][]string + headerPresent []string + headerNotPresent []string query map[string][]string queryPresent []string + queryNotPresent []string cookie []Cookie cookiePresent []string cookieNotPresent []string @@ -336,6 +339,16 @@ func (r *MockRequest) Headers(headers map[string]string) *MockRequest { return r } +func (r *MockRequest) HeaderPresent(key string) *MockRequest { + r.headerPresent = append(r.headerPresent, key) + return r +} + +func (r *MockRequest) HeaderNotPresent(key string) *MockRequest { + r.headerNotPresent = append(r.headerNotPresent, key) + return r +} + func (r *MockRequest) Query(key, value string) *MockRequest { r.query[key] = append(r.query[key], value) return r @@ -353,6 +366,11 @@ func (r *MockRequest) QueryPresent(key string) *MockRequest { return r } +func (r *MockRequest) QueryNotPresent(key string) *MockRequest { + r.queryNotPresent = append(r.queryNotPresent, key) + return r +} + func (r *MockRequest) Cookie(name, value string) *MockRequest { r.cookie = append(r.cookie, Cookie{name: &name, value: &value}) return r @@ -519,6 +537,24 @@ var headerMatcher = func(req *http.Request, spec *MockRequest) error { return nil } +var headerPresentMatcher = func(req *http.Request, spec *MockRequest) error { + for _, header := range spec.headerPresent { + if req.Header.Get(header) == "" { + return fmt.Errorf("expected header '%s' was not present", header) + } + } + return nil +} + +var headerNotPresentMatcher = func(req *http.Request, spec *MockRequest) error { + for _, header := range spec.headerNotPresent { + if req.Header.Get(header) != "" { + return fmt.Errorf("unexpected header '%s' was present", header) + } + } + return nil +} + var queryParamMatcher = func(req *http.Request, spec *MockRequest) error { mockQueryParams := spec.query for key, values := range mockQueryParams { @@ -556,6 +592,15 @@ var queryPresentMatcher = func(req *http.Request, spec *MockRequest) error { return nil } +var queryNotPresentMatcher = func(req *http.Request, spec *MockRequest) error { + for _, query := range spec.queryNotPresent { + if req.URL.Query().Get(query) != "" { + return fmt.Errorf("unexpected query param '%s' present", query) + } + } + return nil +} + var cookieMatcher = func(req *http.Request, spec *MockRequest) error { for _, c := range spec.cookie { foundCookie, _ := req.Cookie(*c.name) @@ -651,8 +696,11 @@ var defaultMatchers = []Matcher{ schemeMatcher, methodMatcher, headerMatcher, + headerPresentMatcher, + headerNotPresentMatcher, queryParamMatcher, queryPresentMatcher, + queryNotPresentMatcher, bodyMatcher, cookieMatcher, cookiePresentMatcher, diff --git a/mocks_test.go b/mocks_test.go index 51eaaa1..80352a3 100644 --- a/mocks_test.go +++ b/mocks_test.go @@ -15,27 +15,6 @@ import ( "github.com/stretchr/testify/assert" ) -func TestMocks_QueryPresent(t *testing.T) { - tests := []struct { - requestUrl string - queryParam string - expectedError error - }{ - {"http://test.com/v1/path?a=1", "a", nil}, - {"http://test.com/v1/path", "a", errors.New("expected query param a not received")}, - {"http://test.com/v1/path?c=1", "b", errors.New("expected query param b not received")}, - {"http://test.com/v2/path?b=2&a=1", "a", nil}, - } - for _, test := range tests { - t.Run(test.requestUrl, func(t *testing.T) { - req := httptest.NewRequest(http.MethodGet, test.requestUrl, nil) - mockRequest := NewMock().Get(test.requestUrl).QueryPresent(test.queryParam) - matchError := queryPresentMatcher(req, mockRequest) - assert.Equal(t, test.expectedError, matchError) - }) - } -} - func TestMocks_Cookie_Matches(t *testing.T) { reqURL := "http://test.com/v1/path" req := httptest.NewRequest(http.MethodGet, reqURL, nil) @@ -213,6 +192,54 @@ func TestMocks_MockRequest_Header_WorksWithHeaders(t *testing.T) { assert.Nil(t, matchError) } +func TestMocks_HeaderPresentMatcher(t *testing.T) { + tests := map[string]struct { + requestHeaders map[string]string + headerPresent string + expectedError error + }{ + "present": {map[string]string{"A": "123", "X": "456"}, "X", nil}, + "not present": {map[string]string{"A": "123"}, "C", errors.New("expected header 'C' was not present")}, + } + for name, test := range tests { + t.Run(name, func(t *testing.T) { + req := httptest.NewRequest(http.MethodGet, "/assert", nil) + for k, v := range test.requestHeaders { + req.Header.Add(k, v) + } + mockRequest := NewMock().Get("/assert").HeaderPresent(test.headerPresent) + + matchError := headerPresentMatcher(req, mockRequest) + + assert.Equal(t, test.expectedError, matchError) + }) + } +} + +func TestMocks_HeaderNotPresentMatcher(t *testing.T) { + tests := map[string]struct { + requestHeaders map[string]string + headerNotPresent string + expectedError error + }{ + "not present": {map[string]string{"A": "123"}, "C", nil}, + "present": {map[string]string{"A": "123", "X": "456"}, "X", errors.New("unexpected header 'X' was present")}, + } + for name, test := range tests { + t.Run(name, func(t *testing.T) { + req := httptest.NewRequest(http.MethodGet, "/assert", nil) + for k, v := range test.requestHeaders { + req.Header.Add(k, v) + } + mockRequest := NewMock().Get("/assert").HeaderNotPresent(test.headerNotPresent) + + matchError := headerNotPresentMatcher(req, mockRequest) + + assert.Equal(t, test.expectedError, matchError) + }) + } +} + func TestMocks_QueryMatcher(t *testing.T) { tests := []struct { requestUrl string @@ -247,6 +274,48 @@ func TestMocks_QueryParams_DoesNotOverwriteQuery(t *testing.T) { assert.Nil(t, matchError) } +func TestMocks_QueryPresent(t *testing.T) { + tests := []struct { + requestUrl string + queryParam string + expectedError error + }{ + {"http://test.com/v1/path?a=1", "a", nil}, + {"http://test.com/v1/path", "a", errors.New("expected query param a not received")}, + {"http://test.com/v1/path?c=1", "b", errors.New("expected query param b not received")}, + {"http://test.com/v2/path?b=2&a=1", "a", nil}, + } + for _, test := range tests { + t.Run(test.requestUrl, func(t *testing.T) { + req := httptest.NewRequest(http.MethodGet, test.requestUrl, nil) + mockRequest := NewMock().Get(test.requestUrl).QueryPresent(test.queryParam) + matchError := queryPresentMatcher(req, mockRequest) + assert.Equal(t, test.expectedError, matchError) + }) + } +} + +func TestMocks_QueryNotPresent(t *testing.T) { + tests := []struct { + queryString string + queryParam string + expectedError error + }{ + {"http://test.com/v1/path?a=1", "a", errors.New("unexpected query param 'a' present")}, + {"http://test.com/v1/path", "a", nil}, + {"http://test.com/v1/path?c=1", "b", nil}, + {"http://test.com/v2/path?b=2&a=1", "a", errors.New("unexpected query param 'a' present")}, + } + for _, test := range tests { + t.Run(test.queryString, func(t *testing.T) { + req := httptest.NewRequest(http.MethodGet, test.queryString, nil) + mockRequest := NewMock().Get("http://test.com/v1/path" + test.queryString).QueryNotPresent(test.queryParam) + matchError := queryNotPresentMatcher(req, mockRequest) + assert.Equal(t, test.expectedError, matchError) + }) + } +} + func TestMocks_SchemeMatcher(t *testing.T) { tests := []struct { requestUrl string