I'm kinda new in Go, so, sorry if this is a silly question.
I have been recently trying some API with Echo. I'm trying to test a route(POST) handler of Go echo that gets a json and puts it in an array. Bellow is the code for the handler main.go and for the test test_main.go
main.go
type Houses struct {
Name string `json:"name,ommitempty"`
Address string `json:"address,omitempty"`
}
var houses []Houses
func newHouse(c echo.Context) error {
m := echo.Map{}
if err := c.Bind(&m); err != nil {
return err
}
dv := Houses{
Name: m["name"].(string),
Address: m["address"].(string),
}
houses = append(houses, dv)
js, _ := json.Marshal(houses)
fmt.Println(fmt.Sprintf("%s", js))
return c.JSON(http.StatusOK, string(js))
}
test_main.go
import (
"net/http"
"net/http/httptest"
"strings"
"testing"
"github.com/labstack/echo"
"github.com/stretchr/testify/assert"
)
var userJSON = `{"name":"Jhon Doe","address":"High St."}`
func TestModel(t *testing.T) {
url := "/new_house"
e := echo.New()
req, err := http.NewRequest(http.MethodPost, url, strings.NewReader(userJSON))
req.Header.Set("Content-Type", "application/json")
if err != nil {
t.Errorf("The request could not be created because of: %v", err)
}
rec := httptest.NewRecorder()
c := e.NewContext(req, rec)
// c.SetPath("/new_house")
// c.JSON(http.StatusOK, Devices{"Jhon Doe", "Middle Way"})
res := rec.Result()
defer res.Body.Close()
if assert.NoError(t, newHouse(c)) {
assert.Equal(t, http.StatusOK, rec.Code)
assert.Equal(t, "["+userJSON+"]", rec.Body.String())
}
}
The test fails with the error shown bellow even though the handler works properly if called by curl.
[{"name":"Jhon Doe","address":"High St."}]
--- FAIL: TestModel (0.00s)
/home/gaidaros/Code/echo-badger/models/model_test.go:34:
Error Trace: model_test.go:34
Error: Not equal:
expected: "[{\"name\":\"Jhon Doe\",\"address\":\"High St.\"}]"
actual : "\"[{\\\"name\\\":\\\"Jhon Doe\\\",\\\"address\\\":\\\"High St.\\\"}]\""
Diff:
--- Expected
+++ Actual
@@ -1 +1 @@
-[{"name":"Jhon Doe","address":"High St."}]
+"[{\"name\":\"Jhon Doe\",\"address\":\"High St.\"}]"
Test: TestModel
FAIL
exit status 1
After several days of struggling over it I couldn't figure out how to make the actual output to match the expected, so I'm posting here in hopes of getting past this obstacle. Any help is appreciated!
You are calling
json.Marshal
on the[]Houses
, which marshals it to a JSON string, then you are callingecho.Context.JSON
with the JSON string, which internally callsjson.Marshal
. Double marshalling causes the escaping. See example. (error checking omitted for brevity)https://play.golang.org/p/nYvHS4huy0M
Your solution is to just pass the slice to your
c.JSON
call. As a side note, you should be able to pass the struct toc.Bind
instead of using a map with type assertions.