Skip to content

Commit

Permalink
custom unmarshalling
Browse files Browse the repository at this point in the history
  • Loading branch information
Jesse Michael committed Jan 25, 2018
1 parent 841b442 commit 1b3a4b2
Show file tree
Hide file tree
Showing 7 changed files with 194 additions and 5 deletions.
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@ Go-Rest-Assured keeps track of the Assured Calls you have stubbed out and the Ca
- Method
- Response
- Headers
- Callbacks

Set these fields as a *Given* call through the client or a HTTP request to the service directly and they will be returned from the Go Rest Assured API when you hit the *When* endpoint. The Calls you stub out are uniquie mapped with an identity of their Method and Path. If you stub multiple calls to the same Method and Path, the responses will cycle through your stubs based on the order they were created.
Set these fields as a *Given* call through the client or a HTTP request to the service directly and they will be returned from the Go Rest Assured API when you hit the *When* endpoint. The Calls you stub out are uniquely mapped with an identity of their Method and Path. If you stub multiple calls to the same Method and Path, the responses will cycle through your stubs based on the order they were created.

If loading callbacks from a JSON file, the call unmarshaller will attempt to read the resource field as a relative file, or else a quoted string, or else just a byte slice.

## Running

Expand Down
41 changes: 39 additions & 2 deletions assured/call.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
package assured

import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strconv"
)

// Call is a structure containing a request that is stubbed or made
Expand All @@ -10,7 +15,7 @@ type Call struct {
Method string `json:"method"`
StatusCode int `json:"status_code"`
Headers map[string]string `json:"headers"`
Response []byte `json:"response,omitempty"`
Response CallResponse `json:"response,omitempty"`
Callbacks []Callback `json:"callbacks,omitempty"`
}

Expand All @@ -27,11 +32,43 @@ func (c Call) String() string {
return rawString
}

// CallResponse allows control over the Call's Response encoding
type CallResponse []byte

// UnmarshalJSON is a custom implementation for JSON Unmarshalling for the CallResponse
// Unmarshalling will first check if the data is a local filepath that can be read
// Else it will check if the data is stringified JSON and un-stringify the data to use
// or Else it will just use the []byte
func (response *CallResponse) UnmarshalJSON(data []byte) error {
unmarshaled := []byte{}
if err := json.Unmarshal(data, &unmarshaled); err != nil {
// The data is a []byte, so use it
unmarshaled = data
}

if s, err := strconv.Unquote(string(unmarshaled)); err == nil {
absPath, _ := filepath.Abs(s)
if _, err := os.Stat(absPath); err == nil {
// The data is a path that exists, therefore we will read the file
if file, err := ioutil.ReadFile(absPath); err == nil {
*response = file
return nil
}
}
// The data is stringified JSON, therefore we eill use the unquoted JSON
*response = []byte(s)
return nil
}

*response = unmarshaled
return nil
}

// Callback is a structure containing a callback that is stubbed
type Callback struct {
Target string `json:"target"`
Method string `json:"method"`
Delay int `json:"delay,omitempty"`
Headers map[string]string `json:"headers"`
Response []byte `json:"response,omitempty"`
Response CallResponse `json:"response,omitempty"`
}
106 changes: 106 additions & 0 deletions assured/call_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package assured

import (
"encoding/json"
"testing"

"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -34,3 +35,108 @@ func TestCallStringNil(t *testing.T) {

require.Equal(t, "", call.String())
}

func TestCallUnmarshalNoResponse(t *testing.T) {
raw := `{
"path": "teapot/assured",
"method": "POST",
"status_code": 418,
"headers": {"Content-Length": "0", "User-Agent": "Go-http-client/1.1", "Accept-Encoding": "gzip"}
}`

call := Call{}
err := json.Unmarshal([]byte(raw), &call)
require.NoError(t, err)
require.Equal(t, *testCall3(), call)
}

func TestCallUnmarshalString(t *testing.T) {
raw := `{
"path": "test/assured",
"method": "GET",
"status_code": 409,
"headers": {"Content-Length": "5", "User-Agent": "Go-http-client/1.1", "Accept-Encoding": "gzip"},
"response": "error"
}`

call := Call{}
err := json.Unmarshal([]byte(raw), &call)
require.NoError(t, err)
require.Equal(t, *testCall2(), call)
}

func TestCallUnmarshalJSON(t *testing.T) {
raw := `{
"path": "test/assured",
"method": "GET",
"status_code": 200,
"headers": {"Content-Length": "17", "User-Agent": "Go-http-client/1.1", "Accept-Encoding": "gzip"},
"response": "{\"assured\": true}"
}`

call := Call{}
err := json.Unmarshal([]byte(raw), &call)
require.NoError(t, err)
require.Equal(t, *testCall1(), call)
}

func TestCallUnmarshalBytes(t *testing.T) {
raw := `{
"path": "test/assured",
"method": "GET",
"status_code": 200,
"headers": {"Content-Length": "17", "User-Agent": "Go-http-client/1.1", "Accept-Encoding": "gzip"},
"response": "eyJhc3N1cmVkIjogdHJ1ZX0="
}`

call := Call{}
err := json.Unmarshal([]byte(raw), &call)
require.NoError(t, err)
require.Equal(t, *testCall1(), call)
}

func TestCallUnmarshalFile(t *testing.T) {
raw := `{
"path": "test/assured",
"method": "GET",
"status_code": 200,
"headers": {"Content-Length": "17", "User-Agent": "Go-http-client/1.1", "Accept-Encoding": "gzip"},
"response": "../testdata/assured.json"
}`

call := Call{}
err := json.Unmarshal([]byte(raw), &call)
require.NoError(t, err)
require.Equal(t, *testCall1(), call)
}

func TestCallUnmarshalCallbacks(t *testing.T) {
raw := `{
"path": "test/assured",
"method": "GET",
"status_code": 200,
"headers": {"Content-Length": "17", "User-Agent": "Go-http-client/1.1", "Accept-Encoding": "gzip"},
"response": "../testdata/assured.json",
"callbacks": [
{
"target": "http://faketarget.com/
"method": "POST",
"response": "{\"done\": true}",
"headers": {"Assured-Callback-Key": "call-key", "Assured-Callback-Target": "http://faketarget.com/"}}
]
}`
expected := *testCall1()
expected.Callbacks = []Callback{
Callback{
Target: "http://faketarget.com/",
Response: []byte(`{"done": true}`),
Method: "POST",
Headers: map[string]string{"Assured-Callback-Key": "call-key", "Assured-Callback-Target": "http://faketarget.com/"},
},
}

call := Call{}
err := json.Unmarshal([]byte(raw), &call)
require.NoError(t, err)
require.Equal(t, expected, call)
}
1 change: 1 addition & 0 deletions testdata/assured.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"assured": true}
42 changes: 42 additions & 0 deletions testdata/callbacks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
[
{
"path": "test/assured",
"method": "GET",
"status_code": 201,
"response": "testdata/assured.json",
"headers": {
"Content-Length": "17",
"User-Agent": "Go-http-client/1.1",
"Accept-Encoding": "gzip"
}
},
{
"path": "test/assured",
"method": "GET",
"status_code": 200,
"response": "testdata/image.jpg",
"headers": {
"Content-Length": "56000",
"Content-Type": "image/jpeg",
"User-Agent": "Go-http-client/1.1"
}
},
{
"path": "teapot/assured",
"method": "POST",
"status_code": 418,
"headers": {
"Content-Length": "0",
"User-Agent": "Go-http-client/1.1",
"Accept-Encoding": "gzip"
},
"callbacks": [
{
"target": "http://localhost:9000/when/capture",
"method": "PUT",
"delay": 5,
"response": "Therefore do not worry about tomorrow, for tomorrow will worry about itself. Each day has enough trouble of its own."
}
]
}
]
4 changes: 2 additions & 2 deletions testdata/calls.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"path": "test/assured",
"method": "GET",
"status_code": 200,
"response": "eyJhc3N1cmVkIjogdHJ1ZX0=",
"response": "{\"assured\": true}",
"headers": {
"Content-Length": "17",
"User-Agent": "Go-http-client/1.1",
Expand All @@ -14,7 +14,7 @@
"path": "test/assured",
"method": "GET",
"status_code": 409,
"response": "ZXJyb3I=",
"response": "error",
"headers": {
"Content-Length": "5",
"User-Agent": "Go-http-client/1.1",
Expand Down
Binary file added testdata/image.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 1b3a4b2

Please sign in to comment.