iT邦幫忙

2025 iThome 鐵人賽

DAY 14
0

昨天我們用 fake ES 成功寫出第一個 E2E 測試。今天的目標更進一步:

啟動一個本地 Elasticsearch(Docker)並撰寫真正的 ESSearchService 實作,然後寫一個最小的 smoke test,確認 /search 能打通

Step 1:啟動本地 Elasticsearch

先在 docker-compose.yml 裡加入 ES:

version: "3.8"
services:
  es01:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.15.0
    container_name: es01
    environment:
      - discovery.type=single-node
      - xpack.security.enabled=false
    ports:
      - "9200:9200"

啟動:

docker compose up -d es01

確認是否正常:

curl http://localhost:9200/

應該會看到一個 JSON,顯示 cluster name 與版本。

Step 2:實作真 ES Service

我們替換掉昨天的 FakeSearchService,寫一個 ESSearchService:

// es_service.go
package search

import (
    "context"
    "encoding/json"
    "fmt"
    "net/http"
    "strings"
)

type ESSearchService struct {
    Endpoint string
}

func (es *ESSearchService) Search(ctx context.Context, query string) ([]SearchResult, error) {
    body := fmt.Sprintf(`{"query":{"match":{"title":"%s"}}}`, query)

    req, err := http.NewRequestWithContext(ctx, "GET",
        es.Endpoint+"/_search",
        strings.NewReader(body))
    if err != nil {
        return nil, err
    }
    req.Header.Set("Content-Type", "application/json")

    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()

    var raw struct {
        Hits struct {
            Hits []struct {
                ID     string `json:"_id"`
                Source struct {
                    Title string `json:"title"`
                } `json:"_source"`
            } `json:"hits"`
        } `json:"hits"`
    }

    if err := json.NewDecoder(resp.Body).Decode(&raw); err != nil {
        return nil, err
    }

    results := []SearchResult{}
    for _, h := range raw.Hits.Hits {
        results = append(results, SearchResult{
            ID:    h.ID,
            Title: h.Source.Title,
        })
    }
    return results, nil
}

Step 3:建立測試資料

先插入一筆假文件:

curl -X POST "http://localhost:9200/books/_doc/1" \
  -H 'Content-Type: application/json' \
  -d '{"title":"Golang 101"}'

刷新 index

curl -X POST "http://localhost:9200/books/_refresh"

Step 4:寫 Smoke Test

這裡我們不用 httptest,直接從 SearchService 驗證:

// es_service_test.go
func TestESSearchService_Smoke(t *testing.T) {
    svc := &search.ESSearchService{Endpoint: "http://localhost:9200/books"}

    ctx := context.Background()
    results, err := svc.Search(ctx, "golang")
    if err != nil {
        t.Fatalf("search error: %v", err)
    }
    if len(results) == 0 {
        t.Fatalf("expected at least 1 result, got 0")
    }
    t.Logf("got %+v", results[0])
}

執行:

go test -run TestESSearchService_Smoke ./...

會看到測試成功,並印出我們插入的 Golang 101。

Step 5:小結

今天我們完成了:

  1. 用 Docker 啟動本機 ES。
  2. 實作 ESSearchService,真實呼叫 _search。
  3. 寫第一個 smoke test,確認從 Go 到 ES 的路徑是通的。

這樣,我們的 /search API 已經能夠打到真實資料庫 🎉

明天,我們要進行最後的 Golang Phase 穩定化:清理目錄、補測試、寫 README,為進入 Elasticsearch Phase 做準備。


上一篇
Day 13 - 整合測試:以假 ES 寫 E2E
系列文
用 Golang + Elasticsearch + Kubernetes 打造雲原生搜尋服務14
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言