Я пишу тест для промежуточного программного обеспечения эластичного поиска, где я использую функцию для создания тестовых серверов, в которой я передаю часть структур конфигурации для каждого теста, а в функции-обработчике они повторяются, и ожидаемый ответ записывается в Автор ответов. Это моя функция.
func newMockClient(url string) (*elasticsearch, error) {
client, err := elastic.NewSimpleClient(elastic.SetURL(url))
if err != nil {
return nil, fmt.Errorf("error while initializing elastic client: %v", err)
}
es := &elasticsearch{
url: url,
client: client,
}
return es, nil
}
type ServerSetup struct {
Method, Path, Body, Response string
HTTPStatus int
}
func buildTestServer(t *testing.T, setups []*ServerSetup) *httptest.Server {
handlerFunc := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
requestBytes, _ := ioutil.ReadAll(r.Body)
requestBody := string(requestBytes)
matched := false
for _, setup := range setups {
if r.Method == setup.Method && r.URL.EscapedPath() == setup.Path {
matched = true
if setup.HTTPStatus == 0 {
w.WriteHeader(http.StatusOK)
} else {
w.WriteHeader(setup.HTTPStatus)
}
_, err := w.Write([]byte(setup.Response))
if err != nil {
t.Fatalf("Unable to write test server response: %v", err)
}
}
}
if !matched {
t.Fatalf("No requests matched setup. Got method %s, Path %s, body %s", r.Method, r.URL.EscapedPath(), requestBody)
}
})
return httptest.NewServer(handlerFunc)
}
Копируется с github.com/github/vulcanizer
. Когда я запускаю один тест с использованием этого, он работает нормально. Например, этот тест
func TestCreateIndex(t *testing.T) {
setup := &ServerSetup{
Method: "PUT",
Path: "/test",
Response: `{"acknowledged": true, "shards_acknowledged": true, "index": "test"}`,
}
ts := buildTestServer(t, []*ServerSetup{setup})
es, _ := newMockClient(ts.URL)
err := es.createIndex(context.Background(), "test", nil)
if err != nil {
t.Fatalf("Index creation failed with error: %v\n", err)
}
}
Но когда я пытаюсь проверить различные варианты поведения в одном тесте, подобном этому, я получаю ошибку http: multiple response.WriteHeader calls
func TestDeleteIndex(t *testing.T) {
setup := &ServerSetup{
Method: "DELETE",
Path: "/test",
Response: `{"acknowledged": true}`,
}
errSetup := &ServerSetup{
Method: "DELETE",
Path: "/test",
Response: `{"acknowledged": false}`,
}
ctx := context.Background()
ts := buildTestServer(t, []*ServerSetup{setup, errSetup})
defer ts.Close()
es, _ := newMockClient(ts.URL)
err := es.deleteIndex(ctx, "test")
if err != nil {
t.Fatalf("Index creation failed with error: %v\n", err)
}
err = es.deleteIndex(ctx, "test")
if err == nil {
t.Fatal("Expected error but not found")
}
}
Я предполагаю, что это из-за того факта, что когда я запускаю deleteIndex во второй раз, он снова отправляет эхо-запрос на сервер, но средство записи ответов уже было записано, поэтому он больше ничего не может записать в него.
Есть ли в любом случае проверка в начале функции моего обработчика, например
handlerFunc := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if w != nil{
// clear data in response writer
}
// .........
}