-
Notifications
You must be signed in to change notification settings - Fork 0
/
mock.go
161 lines (133 loc) · 4.08 KB
/
mock.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
package httpx
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"github.com/JudithTorresc3ntro/omni-gocommon/jsonx"
"github.com/pkg/errors"
)
// MockRequestor is a requestor which can be mocked with responses for given URLs
type MockRequestor struct {
mocks map[string][]MockResponse
}
// NewMockRequestor creates a new mock requestor with the given mocks
func NewMockRequestor(mocks map[string][]MockResponse) *MockRequestor {
return &MockRequestor{mocks: mocks}
}
// Do returns the mocked reponse for the given request
func (r *MockRequestor) Do(client *http.Client, request *http.Request) (*http.Response, error) {
url := request.URL.String()
mockedResponses := r.mocks[url]
if len(mockedResponses) == 0 {
panic(fmt.Sprintf("missing mock for URL %s", url))
}
// pop the next mocked response for this URL
mocked := mockedResponses[0]
r.mocks[url] = mockedResponses[1:]
if mocked.Status == 0 {
return nil, errors.New("unable to connect to server")
}
return mocked.Make(request), nil
}
// HasUnused returns true if there are unused mocks leftover
func (r *MockRequestor) HasUnused() bool {
for _, mocks := range r.mocks {
if len(mocks) > 0 {
return true
}
}
return false
}
// Clone returns a clone of this requestor
func (r *MockRequestor) Clone() *MockRequestor {
cloned := make(map[string][]MockResponse)
for url, ms := range r.mocks {
cloned[url] = ms
}
return NewMockRequestor(cloned)
}
func (r *MockRequestor) MarshalJSON() ([]byte, error) {
return jsonx.Marshal(&r.mocks)
}
func (r *MockRequestor) UnmarshalJSON(data []byte) error {
return jsonx.Unmarshal(data, &r.mocks)
}
var _ Requestor = (*MockRequestor)(nil)
type MockResponse struct {
Status int
Headers map[string]string
Body []byte
BodyIsString bool
BodyRepeat int
}
// Make mocks making the given request and returning this as the response
func (m MockResponse) Make(request *http.Request) *http.Response {
header := make(http.Header, len(m.Headers))
for k, v := range m.Headers {
header.Set(k, v)
}
body := m.Body
if m.BodyRepeat > 1 {
body = bytes.Repeat(body, m.BodyRepeat)
}
return &http.Response{
Request: request,
Status: fmt.Sprintf("%d %s", m.Status, http.StatusText(m.Status)),
StatusCode: m.Status,
Proto: "HTTP/1.0",
ProtoMajor: 1,
ProtoMinor: 0,
Header: header,
Body: ioutil.NopCloser(bytes.NewReader(body)),
ContentLength: int64(len(body)),
}
}
// MockConnectionError mocks a connection error
var MockConnectionError = MockResponse{Status: 0, Headers: nil, Body: []byte{}, BodyIsString: true, BodyRepeat: 0}
// NewMockResponse creates a new mock response from a string
func NewMockResponse(status int, headers map[string]string, body string) MockResponse {
return MockResponse{Status: status, Headers: headers, Body: []byte(body), BodyIsString: true, BodyRepeat: 0}
}
//------------------------------------------------------------------------------------------
// JSON Encoding / Decoding
//------------------------------------------------------------------------------------------
type mockResponseEnvelope struct {
Status int `json:"status" validate:"required"`
Headers map[string]string `json:"headers,omitempty"`
Body json.RawMessage `json:"body" validate:"required"`
BodyRepeat int `json:"body_repeat,omitempty"`
}
func (m *MockResponse) MarshalJSON() ([]byte, error) {
var body []byte
if m.BodyIsString {
body, _ = jsonx.Marshal(string(m.Body))
} else {
body = m.Body
}
return jsonx.Marshal(&mockResponseEnvelope{
Status: m.Status,
Headers: m.Headers,
Body: body,
BodyRepeat: m.BodyRepeat,
})
}
func (m *MockResponse) UnmarshalJSON(data []byte) error {
e := &mockResponseEnvelope{}
if err := json.Unmarshal(data, e); err != nil {
return err
}
m.Status = e.Status
m.Headers = e.Headers
m.BodyRepeat = e.BodyRepeat
if len(e.Body) > 0 && e.Body[0] == '"' {
var bodyAsString string
json.Unmarshal(e.Body, &bodyAsString)
m.Body = []byte(bodyAsString)
m.BodyIsString = true
} else {
m.Body = e.Body
}
return nil
}