dongying7847 2018-11-05 23:00
浏览 315
已采纳

使用Echo测试POST请求(预期与实际输出)

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!

  • 写回答

1条回答 默认 最新

  • dongyan3237 2018-11-06 04:14
    关注

    You are calling json.Marshal on the []Houses, which marshals it to a JSON string, then you are calling echo.Context.JSON with the JSON string, which internally calls json.Marshal. Double marshalling causes the escaping. See example. (error checking omitted for brevity)

    https://play.golang.org/p/nYvHS4huy0M

    h := &Houses{"Jhon Doe", "High St."}
    d, _ := json.Marshal(h)
    
    // double marshal bad
    d, _ = json.Marshal(string(d))
    
    fmt.Println(string(d))
    // prints "{\"name\":\"Jhon Doe\",\"address\":\"High St.\"}"
    

    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 to c.Bind instead of using a map with type assertions.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 数学的三元一次方程求解
  • ¥20 iqoo11 如何下载安装工程模式
  • ¥15 本题的答案是不是有问题
  • ¥15 关于#r语言#的问题:(svydesign)为什么在一个大的数据集中抽取了一个小数据集
  • ¥15 C++使用Gunplot
  • ¥15 这个电路是如何实现路灯控制器的,原理是什么,怎么求解灯亮起后熄灭的时间如图?
  • ¥15 matlab数字图像处理频率域滤波
  • ¥15 在abaqus做了二维正交切削模型,给刀具添加了超声振动条件后输出切削力为什么比普通切削增大这么多
  • ¥15 ELGamal和paillier计算效率谁快?
  • ¥15 蓝桥杯单片机第十三届第一场,整点继电器吸合,5s后断开出现了问题