You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Golang中为BigQuery查询编写集成测试?

Golang中BigQuery查询表数据的集成测试实现

针对BigQuery的集成测试,推荐使用BigQuery模拟器(无需真实GCP资源,零成本且环境隔离)或专用测试GCP项目。以下是基于模拟器的查询表数据集成测试实现:

测试代码实现

package yourpackage

import (
	"context"
	"fmt"
	"testing"
	"time"

	"cloud.google.com/go/bigquery"
	"github.com/testcontainers/testcontainers-go"
	"github.com/testcontainers/testcontainers-go/modules/bigquery"
	"google.golang.org/api/iterator"
)

func TestQueryBigQueryTable(t *testing.T) {
	t.Parallel()

	// 初始化上下文
	ctx := context.Background()

	// 启动BigQuery模拟器容器(自动管理生命周期)
	bqContainer, err := bigquery.StartContainer(ctx, testcontainers.WithImage("gcr.io/cloud-spanner-emulator/bigquery-emulator:latest"))
	if err != nil {
		t.Fatalf("启动BigQuery模拟器失败: %v", err)
	}
	// 测试结束后终止容器
	t.Cleanup(func() {
		if err := bqContainer.Terminate(ctx); err != nil {
			t.Fatalf("终止BigQuery模拟器失败: %v", err)
		}
	})

	// 创建连接到模拟器的BigQuery客户端
	client, err := bigquery.NewClient(ctx, "test-project-id", bigquery.WithEndpoint(bqContainer.Endpoint))
	if err != nil {
		t.Fatalf("创建BigQuery客户端失败: %v", err)
	}
	defer client.Close()

	// 创建测试数据集
	datasetID := "test_dataset"
	dataset := client.Dataset(datasetID)
	if err := dataset.Create(ctx, nil); err != nil {
		t.Fatalf("创建数据集失败: %v", err)
	}
	// 测试结束后删除数据集及内容
	t.Cleanup(func() {
		if err := dataset.Delete(ctx, bigquery.DeleteContents()); err != nil {
			t.Fatalf("删除数据集失败: %v", err)
		}
	})

	// 创建测试表并定义Schema
	tableID := "test_table"
	schema := bigquery.Schema{
		{Name: "id", Type: bigquery.IntegerFieldType, Required: true},
		{Name: "name", Type: bigquery.StringFieldType, Required: true},
		{Name: "created_at", Type: bigquery.TimestampFieldType, Required: true},
	}
	table := dataset.Table(tableID)
	if err := table.Create(ctx, &bigquery.TableMetadata{Schema: schema}); err != nil {
		t.Fatalf("创建测试表失败: %v", err)
	}

	// 插入测试数据
	testRows := []*bigquery.StructSaver{
		{Struct: struct {
			ID        int64
			Name      string
			CreatedAt time.Time
		}{ID: 1, Name: "Alice", CreatedAt: time.Now()}, Schema: schema},
		{Struct: struct {
			ID        int64
			Name      string
			CreatedAt time.Time
		}{ID: 2, Name: "Bob", CreatedAt: time.Now()}, Schema: schema},
	}
	if _, err := table.Uploader().Put(ctx, testRows); err != nil {
		t.Fatalf("插入测试数据失败: %v", err)
	}

	// 执行目标查询
	query := client.Query(fmt.Sprintf(`
		SELECT id, name FROM %s.%s WHERE id > 0
	`, datasetID, tableID))
	job, err := query.Run(ctx)
	if err != nil {
		t.Fatalf("执行查询失败: %v", err)
	}

	// 读取查询结果
	resultIter, err := job.Read(ctx)
	if err != nil {
		t.Fatalf("读取查询结果失败: %v", err)
	}

	// 解析并验证结果
	var retrievedRows []struct {
		ID   int64  `bigquery:"id"`
		Name string `bigquery:"name"`
	}
	for {
		var row struct {
			ID   int64  `bigquery:"id"`
			Name string `bigquery:"name"`
		}
		err := resultIter.Next(&row)
		if err == iterator.Done {
			break
		}
		if err != nil {
			t.Fatalf("遍历结果失败: %v", err)
		}
		retrievedRows = append(retrievedRows, row)
	}

	// 断言结果符合预期
	if len(retrievedRows) != 2 {
		t.Fatalf("预期2条数据,实际得到%d条", len(retrievedRows))
	}
	if retrievedRows[0].ID != 1 || retrievedRows[0].Name != "Alice" {
		t.Fatalf("第一条数据不符合预期: %+v", retrievedRows[0])
	}
	if retrievedRows[1].ID != 2 || retrievedRows[1].Name != "Bob" {
		t.Fatalf("第二条数据不符合预期: %+v", retrievedRows[1])
	}
}

关键说明

  • 依赖安装:执行以下命令安装所需依赖
    go get cloud.google.com/go/bigquery github.com/testcontainers/testcontainers-go github.com/testcontainers/testcontainers-go/modules/bigquery
    
  • 手动启动模拟器替代方案:若不想用Testcontainers,可手动启动BigQuery模拟器,设置环境变量BIGQUERY_EMULATOR_HOST,客户端会自动连接,无需指定WithEndpoint
  • 真实GCP项目适配:替换test-project-id为你的测试项目ID,确保测试账号拥有BigQuery数据集/表的读写权限,测试后及时清理资源避免产生费用
  • 资源自动清理:使用t.Cleanup()确保测试后自动清理模拟器、数据集和表,避免环境污染

内容的提问来源于stack exchange,提问作者Yuseferi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 23:01:32