*JSONEquals() testhelper methods.
These are helpful for testing .ToXyzMap() methods, in particular.
diff --git a/testhelper/convenience.go b/testhelper/convenience.go
index ca27cad..adb77e5 100644
--- a/testhelper/convenience.go
+++ b/testhelper/convenience.go
@@ -1,6 +1,7 @@
package testhelper
import (
+ "encoding/json"
"fmt"
"path/filepath"
"reflect"
@@ -9,25 +10,32 @@
"testing"
)
+const (
+ logBodyFmt = "\033[1;31m%s %s\033[0m"
+ greenCode = "\033[0m\033[1;32m"
+ yellowCode = "\033[0m\033[1;33m"
+ resetCode = "\033[0m\033[1;31m"
+)
+
func prefix(depth int) string {
_, file, line, _ := runtime.Caller(depth)
return fmt.Sprintf("Failure in %s, line %d:", filepath.Base(file), line)
}
func green(str interface{}) string {
- return fmt.Sprintf("\033[0m\033[1;32m%#v\033[0m\033[1;31m", str)
+ return fmt.Sprintf("%s%#v%s", greenCode, str, resetCode)
}
func yellow(str interface{}) string {
- return fmt.Sprintf("\033[0m\033[1;33m%#v\033[0m\033[1;31m", str)
+ return fmt.Sprintf("%s%#v%s", yellowCode, str, resetCode)
}
func logFatal(t *testing.T, str string) {
- t.Fatalf("\033[1;31m%s %s\033[0m", prefix(3), str)
+ t.Fatalf(logBodyFmt, prefix(3), str)
}
func logError(t *testing.T, str string) {
- t.Errorf("\033[1;31m%s %s\033[0m", prefix(3), str)
+ t.Errorf(logBodyFmt, prefix(3), str)
}
type diffLogger func([]string, interface{}, interface{})
@@ -248,6 +256,58 @@
})
}
+// isJSONEquals is a utility function that implements JSON comparison for AssertJSONEquals and
+// CheckJSONEquals.
+func isJSONEquals(t *testing.T, expectedJSON string, actual interface{}) bool {
+ var parsedExpected interface{}
+ err := json.Unmarshal([]byte(expectedJSON), &parsedExpected)
+ if err != nil {
+ t.Errorf("Unable to parse expected value as JSON: %v", err)
+ return false
+ }
+
+ if !reflect.DeepEqual(parsedExpected, actual) {
+ prettyExpected, err := json.MarshalIndent(parsedExpected, "", " ")
+ if err != nil {
+ t.Logf("Unable to pretty-print expected JSON: %v\n%s", err, expectedJSON)
+ } else {
+ // We can't use green() here because %#v prints prettyExpected as a byte array literal, which
+ // is... unhelpful. Converting it to a string first leaves "\n" uninterpreted for some reason.
+ t.Logf("Expected JSON:\n%s%s%s", greenCode, prettyExpected, resetCode)
+ }
+
+ prettyActual, err := json.MarshalIndent(actual, "", " ")
+ if err != nil {
+ t.Logf("Unable to pretty-print actual JSON: %v\n%#v", err, actual)
+ } else {
+ // We can't use yellow() for the same reason.
+ t.Logf("Actual JSON:\n%s%s%s", yellowCode, prettyActual, resetCode)
+ }
+
+ return false
+ }
+ return true
+}
+
+// AssertJSONEquals serializes a value as JSON, parses an expected string as JSON, and ensures that
+// both are consistent. If they aren't, the expected and actual structures are pretty-printed and
+// shown for comparison.
+//
+// This is useful for comparing structures that are built as nested map[string]interface{} values,
+// which are a pain to construct as literals.
+func AssertJSONEquals(t *testing.T, expectedJSON string, actual interface{}) {
+ if !isJSONEquals(t, expectedJSON, actual) {
+ logFatal(t, "The generated JSON structure differed.")
+ }
+}
+
+// CheckJSONEquals is similar to AssertJSONEquals, but nonfatal.
+func CheckJSONEquals(t *testing.T, expectedJSON string, actual interface{}) {
+ if !isJSONEquals(t, expectedJSON, actual) {
+ logError(t, "The generated JSON structure differed.")
+ }
+}
+
// AssertNoErr is a convenience function for checking whether an error value is
// an actual error
func AssertNoErr(t *testing.T, e error) {
diff --git a/testhelper/http_responses.go b/testhelper/http_responses.go
index 481a833..e1f1f9a 100644
--- a/testhelper/http_responses.go
+++ b/testhelper/http_responses.go
@@ -81,33 +81,11 @@
t.Errorf("Unable to read request body: %v", err)
}
- var expectedJSON interface{}
- err = json.Unmarshal([]byte(expected), &expectedJSON)
- if err != nil {
- t.Errorf("Unable to parse expected value as JSON: %v", err)
- }
-
var actualJSON interface{}
err = json.Unmarshal(b, &actualJSON)
if err != nil {
t.Errorf("Unable to parse request body as JSON: %v", err)
}
- if !reflect.DeepEqual(expectedJSON, actualJSON) {
- prettyExpected, err := json.MarshalIndent(expectedJSON, "", " ")
- if err != nil {
- t.Logf("Unable to pretty-print expected JSON: %v\n%s", err, expected)
- } else {
- t.Logf("Expected JSON:\n%s", prettyExpected)
- }
-
- prettyActual, err := json.MarshalIndent(actualJSON, "", " ")
- if err != nil {
- t.Logf("Unable to pretty-print actual JSON: %v\n%s", err, b)
- } else {
- t.Logf("Actual JSON:\n%s", prettyActual)
- }
-
- t.Errorf("Response body did not contain the correct JSON.")
- }
+ CheckJSONEquals(t, expected, actualJSON)
}