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
|
/*
Package mocks provides mocks and helpers used in testing.
*/
package mocks
import (
"fmt"
"io"
"net/http"
)
// Body implements acceptable body over a string.
type Body struct {
s string
b []byte
isOpen bool
closeAttempts int
}
// NewBody creates a new instance of Body.
func NewBody(s string) *Body {
return (&Body{s: s}).reset()
}
// Read reads into the passed byte slice and returns the bytes read.
func (body *Body) Read(b []byte) (n int, err error) {
if !body.IsOpen() {
return 0, fmt.Errorf("ERROR: Body has been closed\n")
}
if len(body.b) == 0 {
return 0, io.EOF
}
n = copy(b, body.b)
body.b = body.b[n:]
return n, nil
}
// Close closes the body.
func (body *Body) Close() error {
if body.isOpen {
body.isOpen = false
body.closeAttempts++
}
return nil
}
// CloseAttempts returns the number of times Close was called.
func (body *Body) CloseAttempts() int {
return body.closeAttempts
}
// IsOpen returns true if the Body has not been closed, false otherwise.
func (body *Body) IsOpen() bool {
return body.isOpen
}
func (body *Body) reset() *Body {
body.isOpen = true
body.b = []byte(body.s)
return body
}
// Sender implements a simple null sender.
type Sender struct {
attempts int
responses []*http.Response
repeatResponse []int
err error
repeatError int
emitErrorAfter int
}
// NewSender creates a new instance of Sender.
func NewSender() *Sender {
return &Sender{}
}
// Do accepts the passed request and, based on settings, emits a response and possible error.
func (c *Sender) Do(r *http.Request) (resp *http.Response, err error) {
c.attempts++
if len(c.responses) > 0 {
resp = c.responses[0]
if resp != nil {
if b, ok := resp.Body.(*Body); ok {
b.reset()
}
}
c.repeatResponse[0]--
if c.repeatResponse[0] == 0 {
c.responses = c.responses[1:]
c.repeatResponse = c.repeatResponse[1:]
}
} else {
resp = NewResponse()
}
if resp != nil {
resp.Request = r
}
if c.emitErrorAfter > 0 {
c.emitErrorAfter--
} else if c.err != nil {
err = c.err
c.repeatError--
if c.repeatError == 0 {
c.err = nil
}
}
return
}
// AppendResponse adds the passed http.Response to the response stack.
func (c *Sender) AppendResponse(resp *http.Response) {
c.AppendAndRepeatResponse(resp, 1)
}
// AppendAndRepeatResponse adds the passed http.Response to the response stack along with a
// repeat count. A negative repeat count will return the reponse for all remaining calls to Do.
func (c *Sender) AppendAndRepeatResponse(resp *http.Response, repeat int) {
if c.responses == nil {
c.responses = []*http.Response{resp}
c.repeatResponse = []int{repeat}
} else {
c.responses = append(c.responses, resp)
c.repeatResponse = append(c.repeatResponse, repeat)
}
}
// Attempts returns the number of times Do was called.
func (c *Sender) Attempts() int {
return c.attempts
}
// SetError sets the error Do should return.
func (c *Sender) SetError(err error) {
c.SetAndRepeatError(err, 1)
}
// SetAndRepeatError sets the error Do should return and how many calls to Do will return the error.
// A negative repeat value will return the error for all remaining calls to Do.
func (c *Sender) SetAndRepeatError(err error, repeat int) {
c.err = err
c.repeatError = repeat
}
// SetEmitErrorAfter sets the number of attempts to be made before errors are emitted.
func (c *Sender) SetEmitErrorAfter(ea int) {
c.emitErrorAfter = ea
}
// T is a simple testing struct.
type T struct {
Name string `json:"name" xml:"Name"`
Age int `json:"age" xml:"Age"`
}
|