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

Golang simulation forces changes to function definitions

WBOY
WBOY forward
2024-02-12 12:33:08 1188browse

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 }

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 }

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")

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 usehttp/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 }

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

A better design is to wrap your api in a clientstructand makegetpricea 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 }
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

For future reference, you should also take a look atgomock, 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!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete