如何在GoFiber中为main.go编写测试代码

huangapple go评论84阅读模式
英文:

How to write test for main.go in GoFiber

问题

以下是我的main.go代码:

func main() {
	app := fiber.New()

	app.Use(recover.New())
	inferenceController := controllers.InferenceController
	middleware := middleware.Middleware

	privateRoutes := routes.PrivateRoutes{InferenceController: inferenceController, Middleware: middleware}
	privateRoutes.Routes(app)

	log.Fatal(app.Listen(":3000"))
}

我正在尝试测试这段代码,但无法找到测试的方法。

英文:

Below is my code for main.go

func main() {
	app := fiber.New()

	app.Use(recover.New())
	inferenceController := controllers.InferenceController
	middleware := middleware.Middleware

	privateRoutes := routes.PrivateRoutes{InferenceController: inferenceController,Middleware: middleware }
	privateRoutes.Routes(app)

	log.Fatal(app.Listen(":3000"))
}

I am trying to test this code but can't figure out the way for testing

答案1

得分: 1

在你的测试中,你实际上需要创建应用程序并注册相关的处理程序。然后使用app.Test()调用处理程序。根据需要创建请求体内容,并检查响应代码和响应体内容。

在这个模型中,你可以根据每个测试用例所需的端点/中间件设置服务器。根据你的具体用例,你可以在此周围提供模拟。

对于你上面的示例,假设你不知道实际的端点,代码可能如下所示:

func TestMyFiberEndpoiunt(t *testing.T) {
    // 设置应用程序
    app := Fiber.New()
    app.Use(recover.New())
    inferenceController := controllers.InferenceController
    middleware := middleware.Middleware
    privateRoutes := routes.PrivateRoutes{InferenceController: inferenceController, Middleware: middleware}
    privateRoutes.Routes(app)

    // 设置请求体
    reqBody := ReqData{SomeData: "something"}
    bodyJson, _ := json.Marshal(&reqBody)
    req := httptest.NewRequest("GET", "/api/v1/endpoint", bytes.NewReader(bodyJson))
    resp, _ := app.Test(req, 10)

    // 检查预期的响应代码
    assert.Equal(t, 200, resp.StatusCode)

    // 检查响应体内容
    respBody := make([]byte, resp.ContentLength)
    _, _ = resp.Body.Read(respBody)
    assert.Equal(t, `{"data":"expected"}`, string(respBody))
}

如果你需要在某些用例中跨多个测试共享有状态的数据,你可以在TestMain中设置服务器并共享为包变量。

如果数据编组对于每个测试用例来说似乎是很大的开销,你可以使用辅助函数,例如:

func GetJsonTestRequestResponse(app *fiber.App, method string, url string, reqBody interface{}) (code int, respBody map[string]interface{}, err error) {
    bodyJson := []byte("")
    if reqBody != nil {
        bodyJson, _ = json.Marshal(reqBody)
    }
    req := httptest.NewRequest(method, url, bytes.NewReader(bodyJson))
    resp, err := app.Test(req, 10)
    code = resp.StatusCode
    // 如果有错误,我们就完成了
    if err != nil {
        return
    }
    // 如果没有响应体内容,我们就完成了
    if resp.ContentLength == 0 {
        return
    }
    bodyData := make([]byte, resp.ContentLength)
    _, _ = resp.Body.Read(bodyData)
    err = json.Unmarshal(bodyData, &respBody)
    return
}

然后测试用例看起来更清晰,编写起来更容易(个人意见)。

type testArg struct {
    Arg1 string
    Arg2 int
}

func TestMyFakeEndpoint(t *testing.T) {
    app := fiber.New()
    defer app.Shutdown()
    app.Post("/test", func(c *fiber.Ctx) error {
        arg := testArg{}
        _ = json.Unmarshal(c.Request().Body(), &arg)
        return c.JSON(arg)
    })

    code, body, err := GetJsonTestRequestResponse(app, "POST", "/test", testArg{"testing", 123})
    assert.Nil(t, err)
    assert.Equal(t, 200, code)
    assert.EqualValues(t, body["Arg1"], "testing")
    assert.EqualValues(t, body["Arg2"], 123)
}
英文:

In your test you actually need to create the app and register the relevent handlers. Then use app.Test() to call the handler. You can create body content as needed and check response codes and body content.

In this model you setup your server with just the endpoints/middleware you need for each test case. You can provide mock's around this if you need, depending on your specific use case.

For your example above, it would be something like the below, not knowing what your actual endpoints are:

func TestMyFiberEndpoiunt(t *testing.T) {
    // Setup the app
    app := Fiber.New()
    app.Use(recover.New())
    inferenceController := controllers.InferenceController
    middleware := middleware.Middleware
    privateRoutes := routes.PrivateRoutes{InferenceController: inferenceController,Middleware: middleware }
    privateRoutes.Routes(app)

    // Setup your request body
    reqBody := ReqData{ SomeData: "something" }
    bodyJson, _ := json.Marshal(&reqBody)
    req := httptest.NewRequest("GET", "/api/v1/endpoint", bytes.NewReader(bodyJson))
    resp, _ := app.Test(req, 10)

    // Check the expected response code
    assert.Equal(t, 200, resp.StatusCode)

    // Check the body content
    respBody := make(byte, resp.ContentLength)
    _, _ = resp.Body.read(respBody)
    assert.Equal(t, `{"data":"expected"}`, string(respBody))
}

If you need stateful data accross multiple tests for some use case, you could setup your server in a TestMain with all the needed routes and share it as a package var.

If the data marshalling seems like a lot of overhead for each test case, you can use a helper function such as:

func GetJsonTestRequestResponse(app *fiber.App, method string, url string, reqBody any) (code int, respBody map[string]any, err error) {
    bodyJson := []byte("")
    if reqBody != nil {
        bodyJson, _ := json.Marshal(reqBody)
    }
    req := httptest.NewRequest(method, url, bytes.NewReader(bodyJson))
    resp, err := app.Test(req, 10)
    code = resp.StatusCode
    // If error we're done
    if err != nil {
	    return
    }
    // If no body content, we're done
    if resp.ContentLength == 0 {
		return
    }
    bodyData := make([]byte, resp.ContentLength)
    _, _ = resp.Body.Read(bodyData)
    err = json.Unmarshal(bodyData, &respBody)
    return
}

Then tests cases look cleaner and are easier to write (imho).

type testArg struct {
	Arg1 string
    Arg2 int
}

func TestMyFakeEndpoint(t *testing.T) {
	app := fiber.New()
	defer app.Shutdown()    
	app.Post("/test", func(c *fiber.Ctx) error {
		arg := testArg{}
		_ = json.Unmarshal(c.Request().Body(), &arg)
		return c.JSON(arg)
	})

    code, body, err := GetJsonTestRequestResponse(app, "POST", "/test", testArg{"testing", 123})
    assert.Nil(t, err)
    assert.Equal(t, 200, code)
    assert.EqualValues(t, body["Arg1"], "testing")
    assert.EqualValues(t, body["Arg2"], 123)
}

huangapple
  • 本文由 发表于 2022年12月7日 21:32:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/74717496.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定