-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathclient.go
154 lines (126 loc) · 3.48 KB
/
client.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
package clientmock
import (
"bytes"
"errors"
"io"
"io/ioutil"
"net/http"
)
// Mock interface serves to create expectations
// for any kind of http.Client action in order to mock
// and test real http.Client behavior.
type Mock interface {
// ExpectMethod sets the method expected on the incoming request
ExpectMethod(method string) Mock
// ExpectBody sets the body expected on the incoming request
ExpectBody(body string) Mock
// ExpectHeader sets the expected headers on the incoming request
ExpectHeader(header http.Header) Mock
// Expectation allows for any custom expectation that follows the Expectation interface
Expectation(exp Expectation) Mock
// ExpectationsMet will return an error if expectations weren't met
ExpectationsMet() error
// ReturnStatus will set the status on returned http.Response
ReturnStatus(status int) Mock
// ReturnBody will set the body on the returned http.Response to the given io.Reader
ReturnBody(body io.Reader) Mock
// ReturnHeader will set the headers on the returned http.Response to the given headers
ReturnHeader(header http.Header) Mock
// ReturnError will return an error instead of a response object
ReturnError(err error) Mock
}
// clientMock is the default mock returned when getting a new client
type clientMock struct {
expectations []Expectation
setters []Setter
err error
}
// RoundTrip implements the RoundTripper interface for use on an http.Client
func (m *clientMock) RoundTrip(req *http.Request) (*http.Response, error) {
// if error is set return it instead of response
if m.err != nil {
return nil, m.err
}
// initialize response with default values
resp := &http.Response{
Status: http.StatusText(http.StatusOK),
StatusCode: http.StatusOK,
Proto: "HTTP/1.1",
ProtoMajor: 1,
ProtoMinor: 1,
Body: ioutil.NopCloser(&bytes.Buffer{}),
ContentLength: 0,
Request: req,
Header: make(http.Header, 0),
}
// process all setters
for _, setter := range m.setters {
setter.Set(resp)
}
// process all expectations
for _, exp := range m.expectations {
exp.Check(req)
}
return resp, nil
}
func (m *clientMock) ExpectMethod(method string) Mock {
m.expectations = append(m.expectations, &ExpectedMethod{
method: method,
})
return m
}
func (m *clientMock) ExpectBody(body string) Mock {
m.expectations = append(m.expectations, &ExpectedBody{
body: body,
})
return m
}
func (m *clientMock) ExpectHeader(h http.Header) Mock {
m.expectations = append(m.expectations, &ExpectedHeader{
h: h,
})
return m
}
func (m *clientMock) Expectation(exp Expectation) Mock {
m.expectations = append(m.expectations, exp)
return m
}
func (m *clientMock) ReturnStatus(status int) Mock {
m.setters = append(m.setters, &SetStatusCode{
code: status,
})
return m
}
func (m *clientMock) ReturnBody(body io.Reader) Mock {
m.setters = append(m.setters, &SetBody{
body: body,
})
return m
}
func (m *clientMock) ReturnHeader(header http.Header) Mock {
m.setters = append(m.setters, &SetHeader{
h: header,
})
return m
}
func (m *clientMock) ReturnError(err error) Mock {
m.err = err
return m
}
func (m *clientMock) ExpectationsMet() error {
for _, exp := range m.expectations {
if !exp.Met() {
return errors.New(exp.Message())
}
}
return nil
}
// NewClient create new mockable http.Client
func NewClient() (*http.Client, Mock, error) {
// setup mock
m := &clientMock{}
// return mock and client to caller
return &http.Client{
Transport: m,
}, m, nil
}