Skip to content

Commit

Permalink
Merge pull request #1 from kyokomi/develop
Browse files Browse the repository at this point in the history
get,post method
  • Loading branch information
kyokomi committed Oct 10, 2015
2 parents 7d0054f + 52f6ad4 commit 4008099
Show file tree
Hide file tree
Showing 6 changed files with 336 additions and 90 deletions.
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
# hhth
hhth
=====================

[![Circle CI](https://circleci.com/gh/kyokomi/hhth.svg?style=svg)](https://circleci.com/gh/kyokomi/hhth)
[![Coverage Status](https://coveralls.io/repos/kyokomi/hhth/badge.svg?branch=master&service=github)](https://coveralls.io/github/kyokomi/hhth?branch=master)


hhth is httpHandler test helper library of the golang.

## TODO

- [ ] test
- [ ] example
- [ ] POST
- [x] test
- [x] POST
- [ ] PUT
- [ ] DELETE
- [ ] OPTIONS
Expand Down
18 changes: 18 additions & 0 deletions circle.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
machine:
pre:
- wget https://storage.googleapis.com/golang/go1.5.1.linux-amd64.tar.gz
- tar zxvf go1.5.1.linux-amd64.tar.gz
environment:
GOROOT: ${HOME}/go
PATH: ${GOROOT}/bin:${PATH}
GO15VENDOREXPERIMENT: 1
post:
- go version
test:
pre:
- go get golang.org/x/tools/cmd/cover
- go get github.com/mattn/goveralls
post:
- go vet ./...
- go test -v . -coverprofile=c.out
- goveralls -v -coverprofile=c.out -service=circle-ci -repotoken $COVERALLS_TOKEN
133 changes: 133 additions & 0 deletions hhth.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package hhth

import (
"encoding/json"
"fmt"
"io"
"net/http"
"net/http/httptest"
)

const (
contentTypeJson = "application/json; charset=UTF-8"
)

type HTTPHandlerTestHelper interface {
SetHeader(key, value string)
SetForm(key, value string)

// method
Get(urlStr string, testCase TestCase) Response
Post(urlStr string, bodyType string, body io.Reader, testCase TestCase) Response
}

var _ HTTPHandlerTestHelper = (*httpHandlerTestHelper)(nil)

func New(handler http.Handler) HTTPHandlerTestHelper {
return &httpHandlerTestHelper{
handler: handler,
params: handlerTestParams{
Headers: map[string]string{},
Form: map[string]string{},
},
}
}

type httpHandlerTestHelper struct {
params handlerTestParams
handler http.Handler
}

func (h *httpHandlerTestHelper) Get(urlStr string, testCase TestCase) Response {
h.params.Method = "GET"
h.params.URL = urlStr
return h.do(testCase, nil)
}

func (h *httpHandlerTestHelper) Post(urlStr string, bodyType string, body io.Reader, testCase TestCase) Response {
h.params.Method = "POST"
h.params.URL = urlStr
h.SetHeader("Content-Type", bodyType)
return h.do(testCase, body)
}

func (h *httpHandlerTestHelper) SetHeader(key, value string) {
h.params.Headers[key] = value
}

func (h *httpHandlerTestHelper) SetForm(key, value string) {
h.params.Form[key] = value
}

type handlerTestParams struct {
Method string
URL string
Headers map[string]string
Form map[string]string
}

type Response interface {
Error() error
String() string
JSON(v interface{}) error
}

type response struct {
err error
response *httptest.ResponseRecorder
}

func (r *response) Error() error {
return r.err
}

func (r *response) Result() (*httptest.ResponseRecorder, error) {
return r.response, r.err
}

func (r *response) String() string {
if r.response == nil {
return ""
}
return r.response.Body.String()
}

func (r *response) JSON(v interface{}) error {
if r.err != nil {
return r.err
}
if r.response == nil {
return fmt.Errorf("response is nil")
}

if err := json.Unmarshal(r.response.Body.Bytes(), v); err != nil {
return err
}
return nil
}

func (h *httpHandlerTestHelper) do(testCase TestCase, body io.Reader) *response {
resp := httptest.NewRecorder()
req, err := http.NewRequest(h.params.Method, h.params.URL, body)
if body == nil {
for key, val := range h.params.Form {
req.Form.Set(key, val)
}
}

for key, val := range h.params.Headers {
req.Header.Set(key, val)
}

if err != nil {
return &response{err: err, response: nil}
}

h.handler.ServeHTTP(resp, req)

if err := testCase.Execute(resp); err != nil {
return &response{err: err, response: nil}
}

return &response{err: nil, response: resp}
}
131 changes: 131 additions & 0 deletions hhth_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package hhth_test

import (
"bytes"
"fmt"
"net/http"
"net/url"
"testing"

"github.com/kyokomi/hhth"
)

func TestHogeHandler(t *testing.T) {
hhtHelper := hhth.New(http.DefaultServeMux)

testCase1 := hhth.NewTestCase(http.StatusOK, "text/plain; charset=utf-8")
resp := hhtHelper.Get("/hoge", testCase1)
if resp.Error() != nil {
t.Errorf("error %s", resp.Error())
}
fmt.Println(resp.String())
}

func TestHogeJSONHandler(t *testing.T) {
hhtHelper := hhth.New(http.DefaultServeMux)
testCase := hhth.NewTestCase(http.StatusOK, "application/json; charset=UTF-8")
var resp map[string]interface{}
if err := hhtHelper.Get("/hoge.json", testCase).JSON(&resp); err != nil {
t.Errorf("error %s", err)
}
fmt.Println(resp)
}

func TestHogeHeaderHandler(t *testing.T) {
hhtHelper := hhth.New(http.DefaultServeMux)
hhtHelper.SetHeader("X-App-Hoge", "hoge-header")
testCase := hhth.NewTestCase(http.StatusOK, "text/plain; charset=utf-8")
resp := hhtHelper.Get("/header", testCase)
if resp.Error() != nil {
t.Errorf("error %s", resp.Error())
}
fmt.Println(resp.String())
}

func TestPostHandler(t *testing.T) {
hhtHelper := hhth.New(http.DefaultServeMux)
testCase := hhth.NewTestCase(http.StatusOK, "text/plain; charset=utf-8")

formData := url.Values{}
formData.Set("name", "hoge")
formData.Set("age", "19")

body := bytes.NewBufferString(formData.Encode())
resp := hhtHelper.Post("/post", "application/x-www-form-urlencoded", body, testCase)
if resp.Error() != nil {
t.Errorf("error %s", resp.Error())
}
fmt.Println(resp.String())
}

func init() {
http.HandleFunc("/hoge", hogeHandler)
http.HandleFunc("/hoge.json", hogeJSONHandler)
http.HandleFunc("/header", headerHandler)
http.HandleFunc("/post", postHandler)
}

func hogeHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" {
renderError(http.StatusMethodNotAllowed, w)
return
}

w.WriteHeader(http.StatusOK)
w.Header().Add("Content-Type", "text/plain; charset=utf-8")
w.Write([]byte("hogehoge"))
}

func hogeJSONHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" {
renderError(http.StatusMethodNotAllowed, w)
return
}

w.WriteHeader(http.StatusOK)
w.Header().Add("Content-Type", "application/json; charset=UTF-8")
w.Write([]byte(`{"name": "hogehoge", "age": 20}`))
}

func headerHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" {
renderError(http.StatusMethodNotAllowed, w)
return
}

xAppHoge := r.Header.Get("X-App-Hoge")
if xAppHoge != "hoge-header" {
renderError(http.StatusBadRequest, w)
return
}

w.WriteHeader(http.StatusOK)
w.Header().Add("Content-Type", "text/plain; charset=utf-8")
w.Write([]byte("header ok " + xAppHoge))
}

func postHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" {
renderError(http.StatusMethodNotAllowed, w)
return
}

if err := r.ParseForm(); err != nil {
renderError(http.StatusBadRequest, w)
return
}

if r.PostForm.Encode() != "age=19&name=hoge" {
renderError(http.StatusBadRequest, w)
return
}

w.WriteHeader(http.StatusOK)
w.Header().Add("Content-Type", "text/plain; charset=utf-8")
w.Write([]byte("post ok " + r.PostForm.Encode()))
}

func renderError(statusCode int, w http.ResponseWriter) {
w.WriteHeader(statusCode)
w.Write([]byte(http.StatusText(http.StatusMethodNotAllowed)))
}
86 changes: 0 additions & 86 deletions main.go

This file was deleted.

Loading

0 comments on commit 4008099

Please sign in to comment.