httpread/httpread_test.go
package httpread
import (
"errors"
"io/ioutil"
"net/http"
"strings"
"testing"
"github.com/stretchr/testify/assert"
)
type errorReader struct {
}
func (errorReader) Read(p []byte) (n int, err error) {
return 0, errors.New("error")
}
// TestErrorAtRequest reads from an error-prone source and asserts that the error is propagated.
func TestErrorAtRequest(t *testing.T) {
clientPtr := &http.Client{}
_, err := String(func() (*http.Response, error) {
return clientPtr.Get("asfdnklfnlkanfknaf.afsajf.asfja")
})
assert.Error(t, err)
}
// TestError400 considers 400 bad request as response.
func TestError400(t *testing.T) {
resp := &http.Response{StatusCode: 400, Status: "Bad Request", Body: ioutil.NopCloser(&strings.Reader{})}
_, err := String(func() (*http.Response, error) {
return resp, nil
})
assert.Error(t, err)
}
// TestSuccess follows the regular workflow.
func TestSuccess(t *testing.T) {
resp := &http.Response{StatusCode: 200, Status: "OK", Body: ioutil.NopCloser(strings.NewReader("payload"))}
body, err := String(func() (*http.Response, error) {
return resp, nil
})
assert.NoError(t, err)
assert.Equal(t, "payload", body)
}
// TestStatusCodeGuessing simulates a web server that does not handle status codes very well.
func TestStatusCodeGuessing(t *testing.T) {
resp := &http.Response{StatusCode: 200, Status: "OK", Body: ioutil.NopCloser(strings.NewReader("HTTP/1.0 500 Internal Server Error\nContent-Length: 0\nContent-Type: text/plain; charset=utf-8"))}
_, err := String(func() (*http.Response, error) {
return resp, nil
})
assert.Error(t, err)
}
// TestXMLErrorAtRequest reads from an error-prone source and asserts that the error is propagated.
func TestXMLErrorAtRequest(t *testing.T) {
clientPtr := &http.Client{}
var payload string
err := XML(func() (*http.Response, error) {
return clientPtr.Get("asfdnklfnlkanfknaf.afsajf.asfja")
}, &payload)
assert.Error(t, err)
}
// TestXMLError400 considers 400 bad request as response.
func TestXMLError400(t *testing.T) {
resp := &http.Response{StatusCode: 400, Status: "Bad Request", Body: ioutil.NopCloser(&strings.Reader{})}
var payload string
err := XML(func() (*http.Response, error) {
return resp, nil
}, &payload)
assert.Error(t, err)
}
// TestXMLDecodeError considers a malformed, non-XML payload.
func TestXMLDecodeError(t *testing.T) {
resp := &http.Response{StatusCode: 200, Status: "OK", Body: ioutil.NopCloser(strings.NewReader("no-xml"))}
var payload string
err := XML(func() (*http.Response, error) {
return resp, nil
}, &payload)
assert.Error(t, err)
}
// TestReadFullyXMLSuccess follows the regular workflow.
func TestReadFullyXMLSuccess(t *testing.T) {
resp := &http.Response{StatusCode: 200, Status: "OK", Body: ioutil.NopCloser(strings.NewReader("<dummy></dummy>"))}
var payload string
err := XML(func() (*http.Response, error) {
return resp, nil
}, &payload)
assert.NoError(t, err)
}
// TestReadFullyJSON tests decoding into JSON.
func TestReadFullyJSON(t *testing.T) {
resp := &http.Response{StatusCode: 200, Status: "OK", Body: ioutil.NopCloser(strings.NewReader(`{"a":"b"}`))}
var payload struct {
A string `json:"a"`
}
err := JSON(func() (*http.Response, error) {
return resp, nil
}, &payload)
assert.NoError(t, err)
assert.Equal(t, payload.A, "b")
}
// TestStringDecoder tests decoding into strings.
func TestStringDecoder(t *testing.T) {
assert.Error(t, (&stringDecoder{reader: errorReader{}}).Decode(new(string)))
assert.Error(t, (&stringDecoder{reader: strings.NewReader("somevalue")}).Decode(&struct{}{}))
assert.NoError(t, (&stringDecoder{reader: strings.NewReader("somevalue")}).Decode(new(string)))
}
// TestCsv tests the Csv happy path.
func TestCsv(t *testing.T) {
resp := &http.Response{
StatusCode: 200,
Status: "OK",
Body: ioutil.NopCloser(strings.NewReader("x,y,z\n1,2,3")),
}
records, err := Csv(func() (*http.Response, error) {
return resp, nil
}, ',')
assert.NoError(t, err)
assert.NotNil(t, records)
assert.Len(t, records, 2)
assert.Len(t, records[0], 3)
assert.Len(t, records[1], 3)
}
// TestCsvErrorAtDecoding tests errors at decoding stage.
func TestCsvErrorAtDecoding(t *testing.T) {
resp := &http.Response{
StatusCode: 200,
Status: "OK",
Body: ioutil.NopCloser(&errorReader{}),
}
_, err := Csv(func() (*http.Response, error) {
return resp, nil
}, ',')
assert.Error(t, err)
}
// TestCsvDecoderCalledWithRubbish asserts a panic-free mis-usage when called with anything else than *[][]string.
func TestCsvDecoderCalledWithRubbish(t *testing.T) {
c := csvDecoder{reader: strings.NewReader("x,y,z\n1,2,3"), comma: ','}
err := c.Decode(683)
assert.Error(t, err)
}