Как выполнить модульное тестирование с http в качестве зависимости - PullRequest
0 голосов
/ 15 декабря 2018

У меня есть следующая функция, которая работает как ожидалось.Теперь я хочу запустить модульный тест для него.

func httpClient(cc []string,method http) ([]byte, error) {
    httpClient := http.Client{}
    req, err := http.NewRequest(http.MethodPost, c[0]+"/oauth/token", nil)
    if err != nil {
        fmt.error(err)
    }
    //Here we are passing user and password
    req.SetBasicAuth(c[1], c[2])
    res, err := httpClient.Do(req)
    if err != nil {
        fmt.error(err)
    }
    val, err := ioutil.ReadAll(res.Body)
    if err != nil {
        fmt.error(err)
    }
    defer res.Body.Close()
    return val, nil
}

Проблема в том, что мне нужно что-то, чтобы подделать вызов http, я попытался с помощью следующего, изменить сигнатуру метода и поставить метод и URL какпараметр.Проблема в том, что я не знаю, как притворяться, что POST метод

Это измененный код , чтобы сделать тест более простым

func httpClient(cc []string, method string, url string) ([]byte, error) {
    httpClient := http.Client{}
    req, err := http.NewRequest(method, url, nil)
    if err != nil {
        return nil, errors.Wrap(err, "failed to execute http request")
    }
    //Here we are passing user and password
    req.SetBasicAuth(cc[1], cc[2])
    res, err := httpClient.Do(req)
    if err != nil {
        fmt.error(err)
    }
    val, err := ioutil.ReadAll(res.Body)
    if err != nil {
        fmt.error(err)
    }
    defer res.Body.Close()
    return val, nil
}

Это тест, который я пробую, но все еще не работает , так как мне нужно каким-то образом подделать метод сообщения

func Test_httpClient(t *testing.T) {
    type args struct {
        params    []string
        method string
        url    string
    }
    tests := []struct {
        name    string
        args    args
        want    []byte
        wantErr bool
    }{
        {
            name:    "httpCallTest",
            args:{{"fakeuser", "fakepasswword"},{"post"},{"/any/url"}},
            want:    nil,
            wantErr: false,
        },

    }
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            got, err := httpClient(tt.args.params, tt.args.method, tt.args.url)
            if (err != nil) != tt.wantErr {
                t.Errorf("httpClient() error = %v, wantErr %v", err, tt.wantErr)
                return
            }
            if !reflect.DeepEqual(got, tt.want) {
                t.Errorf("httpClient() = %v, want %v", got, tt.want)
            }
        })
    }
}

Ответы [ 2 ]

0 голосов
/ 15 декабря 2018

Я бы использовал что-то вроде следующего кода.Использование newTestServer(address).run()

import (
    "github.com/gorilla/mux"
    "net/http"
    "sync"
    "time"
)

type testServer struct {
    addr   string
    router *mux.Router
}

// addr can be e.g. `localhost:3030`
// -> your client will do request on `localhost:3030/some/endpoint/path`
func newTestServer(addr string) *testServer {
    router := mux.NewRouter()
    router.HandleFunc(
        "/some/endpoint/path",
        handleEndpoint,
    ).Methods(http.MethodPost)

    return &testServer{
        addr:   addr,
        router: router,
    }
}

func handleEndpoint(writer http.ResponseWriter, request *http.Request) {
    // your implementation
}

func (server *testServer) run() {
    wg := sync.WaitGroup{}
    wg.Add(1)
    go func() {
        wg.Done()
        if err := http.ListenAndServe(server.addr, server.router); err != nil {
            panic(err)
        }
    }()
    wg.Wait()                          // wait for goroutine starts
    time.Sleep(100 * time.Millisecond) // wait for listening starts
}

Но я предполагаю, что тест все равно не пройдет.

// this will panic
// requires 2nd and 3rd item in an array
req.SetBasicAuth(cc[1], cc[2])
0 голосов
/ 15 декабря 2018

Я бы рекомендовал взглянуть на пакет httptest .Он имеет поддельный HTTP-сервер, который хорошо вам подойдет.

func Test_httpClient(t *testing.T){
  var called bool
  defer func(){
    if !called{
      t.Fatal("expected endpoint to be called")
    }
  }()
  expectedValue = "some-value"

  server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request){
    called = true
    u,p,ok := r.BasicAuth()
    if !ok || u != "fakeuser" || p != "fakepassword" {
      t.Fatal("wrong auth")
    }
    w.Write([]byte(expectedValue))
  })

  val, err := httpClient(
   []string{"fakeuser", "fakepasswword"}, 
   http.MethodPost, 
   server.URL,
  )

  if err != nil{
    t.Fatal(err)
  }

  if val != expectedValue {
    t.Fatalf("expected %q to equal %q", val, expectedValue)
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...