У меня есть предыдущий код, который работает следующим образом:
- вызов функции
getData
, которая предоставляет вам данные для выполнения http-запроса
- используйте вывод функции
getData
для выполнения http-запроса.
Раньше это работало, но теперь я хочу сделать для него модульное тестирование, и я прочитал несколько блогов, как сделать эту работу, и кажется, что внедрение зависимостей является ключом для этого. Я пытался подписаться на этот пост .
Я пытаюсь принять код, но не уверен, правильно ли я это сделал.
Идея состоит в том, чтобы использовать функцию getData
в prod с некоторым URL-адресом для выполнения, а в unit test
предоставить другой URL-адрес, аналогичный httptest.NewServer(testHandler)
Как я должен сделать это прямо в Go?
package main
import (
"fmt"
"io/ioutil"
"net/http"
)
type requester interface {
HTTPRequest(c string, i string, mtd string, url string) (p []byte, e error)
}
func (i impl) HTTPRequest(c string, ci string, mtd string, url string) (p []byte, e error) {
req, err := http.NewRequest(mtd, url, nil)
if err != nil {
return nil, err
}
req.SetBasicAuth(c, ci)
res, err := i.client.Do(req)
if err != nil {
return nil, err
}
token, err := ioutil.ReadAll(res.Body)
if err != nil {
return nil, err
}
defer res.Body.Close()
fmt.Println("success")
return token, nil
}
type iData interface {
getData() []string
}
type reqData struct {
f1 string
f2 string
}
func (s reqData) getData() []string {
a := make([]string, 4)
a[2] = "http://www.mocky.io/v2/5c20eccc2e00005c001e0c84"
a[3] = "/oauth/token?grant_type=client_credentials"
return a
}
type ServiceInfo struct {
req requester
data iData
}
type impl struct {
client *http.Client
}
func NewServiceInfo(http requester, data iData) *ServiceInfo {
return &ServiceInfo{
req: http,
data: data,
}
}
// ----This is the function which I need to mock
func (s *ServiceInfo) caller() {
// Function 1 - get the values
reqdata := s.data.getData()
// Function 2 -call to http function
s.req.HTTPRequest(reqdata[0], reqdata[1], "POST", reqdata[2])
}
func main() {
// not sure how to run it
//httpClient := http.Client{}
//d := reqData{f1: "user", f2: "password"}
//s := NewServiceInfo(impl{client: &httpClient}, d.getData())
//s.caller()
}
Тест выглядит примерно так, но на самом деле не уверен, как заставить его работать
It("Test", func() {
// Mock http call
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
u, p, ok := r.BasicAuth()
Ω(ok).Should(Equal(true))
Ω(u).Should(Equal("user"))
Ω(p).Should(Equal("password"))
}))
var httpClient = http.Client{}
si := NewServiceInfo(client{httpClient: &httpClient, url: server.URL})
t, err := si.r.httpReq("user", "password", http.MethodPost)
Ω(token).Should(Equal(string(t)))
Ω(err).ShouldNot(HaveOccurred())
})
Код является всего лишь примером для моего полного кода, поэтому я стараюсь взять его и поставить только соответствующие части
обновление
чтобы было понятнее :)
Что мне нужно, это как правильно (насмехаться) на функцию getData
,
чтобы предоставить url x
в коде продукта и url y
в тесте, нюанс здесь, что мне нужно сделать модульный тест для функции caller
Чтобы заставить это работать, это не проблема , но проблема здесь, чтобы заставить его проверяемый код
https://play.golang.org/p/UQqtZmNS5BK