Golang mock forces to change functions definition

问题描述 投票:0回答:1

我有以下功能:

func getPrice(date string) {
  url := (fmt.Printf("http://endponint/%s", date))
    resp, err := http.Get(url)
    // Unmarshall body and get price
    return price
}

为了对这个函数进行单元测试,我不得不重构为:

func getPrice(client HTTPClient, date string) {
  url := (fmt.Printf("http://endponint/%s", date))
    resp, err := client.Get(url)
    // Unmarshall body and get price
    return price
}

我的测试是这样的:


type MockClient struct {
    Response *http.Response
    Err      error
}

func (m *MockClient) Get(url string) (*http.Response, error) {
    return m.Response, m.Err
}

mockResp := &http.Response{
    StatusCode: http.StatusOK,
    Body:       ioutil.NopCloser(strings.NewReader("mock response")),
}

client := &MockClient{
    Response: mockResp,
    Err:      nil,
}

data, err := getData(client, "http://example.com")

这是在 golang 中测试的唯一方法吗,没有办法模拟未注入函数的 API 吗?

提前致谢。

unit-testing go testing
1个回答
0
投票

使用 Go 进行 HTTP 测试的惯用方法是使用 http/httptestexamples

在您的情况下,您需要做的就是使基本 URL 可注入:

var APIEndpoint = "http://endpoint/"

func getPrice(date string) (int, error) {
  url := (fmt.Printf("%s/%s", APIEndpoint, date))
  resp, err := http.Get(url)
  // Unmarshall body and get price
  return price, nil
}

然后在每个测试中:

srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    // Write the expected response to the writer
}))
defer srv.Close()
APIEndpoint = srv.URL
price, err := getPrice("1/1/2023")
// Handle error, check return

稍微好一点的设计是将您的 API 包装在客户端中

struct
并使
getPrice
成为接收方方法:

type PriceClient struct {
    Endpoint string
}

func (pc *PriceClient) GetPrice(date string) (int, error) {
  url := (fmt.Printf("%s/%s", pc.Endpoint, date))
  resp, err := http.Get(url)
  // Unmarshall body and get price
  return price, nil
}
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    // Write the expected response to the writer
}))
defer srv.Close()
c := &PriceClient{Endpoint: srv.URL}
price, err := c.GetPrice("1/1/2023")
// Handle error, check return

为了将来参考,您还应该看看 gomock,因为您将遇到的大多数其他模拟问题都没有语言内置的解决方案。

© www.soinside.com 2019 - 2024. All rights reserved.