Home > Backend Development > Golang > Golang simulation forces changes to function definitions

Golang simulation forces changes to function definitions

WBOY
Release: 2024-02-12 12:33:08
forward
1266 people have browsed it

Golang simulation forces changes to function definitions

php editor Xiaoxin today brings you an introduction to Golang's simulation of forced change function definitions. Golang is an efficient and concise programming language with a powerful type system. However, in some cases, we may need to modify the definition of an existing function to meet specific needs. This article will introduce to you how to simulate the method of forcibly changing the function definition in Golang. Let's explore it together!

Question content

I have the following functions:

func getprice(date string) {
  url := (fmt.printf("http://endponint/%s", date))
    resp, err := http.get(url)
    // unmarshall body and get price
    return price
}
Copy after login

In order to unit test this function, I was forced to refactor to:

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
}
Copy after login

My test looks like this:

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")
Copy after login

Is this the only way to test in go? Isn't there a way to mock the api that is not injected into the function?

Solution

The idiomatic way to use go for http testing is to use http/httptest (Example)

In your case, all you need to do is make the base url injectable:

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
}
Copy after login

Then in each test:

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
Copy after login

A better design is to wrap your api in a client struct and make getprice a receiver method:

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
}
Copy after login
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
Copy after login

For future reference, you should also take a look at gomock, as most other mocking problems you will encounter have no built-in solutions to the language.

The above is the detailed content of Golang simulation forces changes to function definitions. For more information, please follow other related articles on the PHP Chinese website!

source:stackoverflow.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template