最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Golang使用Docker進(jìn)行集成測(cè)試的示例詳解

 更新時(shí)間:2023年07月27日 08:58:14   作者:江湖十年  
集成測(cè)試需要解決外部依賴問(wèn)題,如?MySQL、Redis、網(wǎng)絡(luò)等依賴,本文就來(lái)聊聊?Go?程序如何使用?Docker?來(lái)解決集成測(cè)試中外部依賴問(wèn)題吧

實(shí)踐表明,有時(shí)程序中某個(gè)模塊雖然可以單獨(dú)工作,但是并不能保證多個(gè)模塊組裝起來(lái)也可以同時(shí)工作,于是就有了集成測(cè)試。

集成測(cè)試需要解決外部依賴問(wèn)題,如 MySQL、Redis、網(wǎng)絡(luò)等依賴,解決這些外部依賴問(wèn)題最佳實(shí)踐則是使用 Docker,本文就來(lái)聊聊 Go 程序如何使用 Docker 來(lái)解決集成測(cè)試中外部依賴問(wèn)題。

登錄程序示例

在 Web 開(kāi)發(fā)中,登錄需求是一個(gè)較為常見(jiàn)的功能。所以,本文就以登錄程序?yàn)槔v解使用 Docker 啟動(dòng) Redis 進(jìn)行集成測(cè)試。

登錄程序如下:

func Login(mobile, smsCode string, rdb *redis.Client) (string, error) {
	ctx := context.Background()
	// 查找驗(yàn)證碼
	captcha, err := GetSmsCaptchaFromRedis(ctx, rdb, mobile)
	if err != nil {
		if err == redis.Nil {
			return "", fmt.Errorf("invalid sms code or expired")
		}
		return "", err
	}
	if captcha != smsCode {
		return "", fmt.Errorf("invalid sms code")
	}
	token, _ := GenerateToken(32)
	err = SetAuthTokenToRedis(ctx, rdb, token, mobile)
	if err != nil {
		return "", err
	}
	return token, nil
}

可以通過(guò)如下方式獲取 Redis 客戶端對(duì)象 rdb

import "github.com/redis/go-redis/v9"
func NewRedisClient() *redis.Client {
	return redis.NewClient(&redis.Options{
		Addr: "localhost:6379",
	})
}

生成隨機(jī) token 的函數(shù)定義如下:

var GenerateToken = func(length int) (string, error) {
	token := make([]byte, length)
	_, err := rand.Read(token)
	if err != nil {
		return "", err
	}
	return base64.URLEncoding.EncodeToString(token)[:length], nil
}

本程序提供了如下幾個(gè)操作 Reids 的函數(shù):

var (
	smsCaptchaExpire    = 5 * time.Minute
	smsCaptchaKeyPrefix = "sms:captcha:%s"
	authTokenExpire    = 24 * time.Hour
	authTokenKeyPrefix = "auth:token:%s"
)
func SetSmsCaptchaToRedis(ctx context.Context, redis *redis.Client, mobile, captcha string) error {
	key := fmt.Sprintf(smsCaptchaKeyPrefix, mobile)
	return redis.Set(ctx, key, captcha, smsCaptchaExpire).Err()
}
func GetSmsCaptchaFromRedis(ctx context.Context, redis *redis.Client, mobile string) (string, error) {
	key := fmt.Sprintf(smsCaptchaKeyPrefix, mobile)
	return redis.Get(ctx, key).Result()
}
func DeleteSmsCaptchaFromRedis(ctx context.Context, redis *redis.Client, mobile string) error {
	key := fmt.Sprintf(smsCaptchaKeyPrefix, mobile)
	return redis.Del(ctx, key).Err()
}
func SetAuthTokenToRedis(ctx context.Context, redis *redis.Client, token, mobile string) error {
	key := fmt.Sprintf(authTokenKeyPrefix, token)
	return redis.Set(ctx, key, mobile, authTokenExpire).Err()
}
func GetAuthTokenFromRedis(ctx context.Context, redis *redis.Client, token string) (string, error) {
	key := fmt.Sprintf(authTokenKeyPrefix, token)
	return redis.Get(ctx, key).Result()
}
func DeleteAuthTokenFromRedis(ctx context.Context, redis *redis.Client, token string) error {
	key := fmt.Sprintf(authTokenKeyPrefix, token)
	return redis.Del(ctx, key).Err()
}

Login 函數(shù)用法如下:

func main() {
	rdb := NewRedisClient()
	token, err := Login("13800001111", "123456", rdb)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(token)
}

使用 Docker 進(jìn)行集成測(cè)試

要想對(duì) Login 函數(shù)進(jìn)行集成測(cè)試,就需要解決 Reids 外部依賴問(wèn)題。

在 Go 程序中,我們可以使用 testcontainers-go 這個(gè)包來(lái)解決,它可以讓我們很方便的在 Docker 中啟動(dòng) Reids 服務(wù)。

安裝 testcontainers-go

$ go get github.com/testcontainers/testcontainers-go

我們可以在測(cè)試代碼開(kāi)始執(zhí)行之前啟動(dòng) Docker 容器來(lái)運(yùn)行 Redis 服務(wù),然后執(zhí)行測(cè)試代碼,最后測(cè)試代碼執(zhí)行完成后再停止并刪除 Docker 容器。

可以定義一個(gè) setup 函數(shù)用來(lái)準(zhǔn)備 Docker 容器:

var rdbClient *redis.Client
func setup() func() {
	ctx := context.Background()
	req := testcontainers.ContainerRequest{
		Image:        "redis:6.0.20-alpine",
		ExposedPorts: []string{"6379/tcp"},
		WaitingFor:   wait.ForLog("Ready to accept connections"),
	}
	redisC, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
		ContainerRequest: req,
		Started:          true,
	})
	if err != nil {
		panic(fmt.Sprintf("failed to start container: %s", err.Error()))
	}
	endpoint, err := redisC.Endpoint(ctx, "")
	if err != nil {
		panic(fmt.Sprintf("failed to get endpoint: %s", err.Error()))
	}
	rdbClient = redis.NewClient(&redis.Options{
		Addr: endpoint,
	})
	// 清理 Redis 容器
	return func() {
		if err := redisC.Terminate(ctx); err != nil {
			panic(fmt.Sprintf("failed to terminate container: %s", err.Error()))
		}
	}
}

可以發(fā)現(xiàn)使用 testcontainers-go 啟動(dòng)一個(gè) Redis 容器非常簡(jiǎn)單,我們指定了 Docker 容器鏡像為 redis:6.0.20-alpine,映射端口為 6379/tcp。

Redis 容器啟動(dòng)后將實(shí)例化的 Redis 客戶端保存到全局變量 rdbClient 中,方便在測(cè)試函數(shù)中使用,setup 函數(shù)最終返回一個(gè) teardown 函數(shù)可以清理容器。

定義 TestMain 函數(shù)如下,作為測(cè)試程序的入口:

func TestMain(m *testing.M) {
	teardown := setup()
	code := m.Run()
	teardown()
	os.Exit(code)
}

為了測(cè)試 Login 函數(shù),我們需要在 Reids 中準(zhǔn)備一些測(cè)試數(shù)據(jù),因?yàn)?Login 函數(shù)內(nèi)部需要查詢 Reids 中的驗(yàn)證碼,所以可以定義一個(gè) setupLogin 函數(shù)來(lái)實(shí)現(xiàn):

func setupLogin(tb testing.TB) func(tb testing.TB) {
	// 準(zhǔn)備測(cè)試數(shù)據(jù)
	err := SetSmsCaptchaToRedis(context.Background(), rdbClient, "18900001111", "123456")
	assert.NoError(tb, err)
	// 清理測(cè)試數(shù)據(jù)
	return func(tb testing.TB) {
		err := DeleteSmsCaptchaFromRedis(context.Background(), rdbClient, "18900001111")
		assert.NoError(tb, err)
		err = DeleteAuthTokenFromRedis(context.Background(), rdbClient, "token")
		assert.NoError(tb, err)
	}
}

setupLogin 函數(shù)返回 teardownLogin 函數(shù)用來(lái)清理 Redis 中的測(cè)試數(shù)據(jù),防止當(dāng)有多個(gè)測(cè)試函數(shù)時(shí)互相影響。

現(xiàn)在可以編寫 Login 函數(shù)的測(cè)試代碼了:

func TestLogin(t *testing.T) {
	teardownLogin := setupLogin(t)
	defer teardownLogin(t)
	// 測(cè)試登錄成功情況
	token, err := Login("18900001111", "123456", rdbClient)
	assert.NoError(t, err)
	assert.Equal(t, "token", token)
	// 檢查 Redis 中是否存在 token
	mobile, err := GetAuthTokenFromRedis(context.Background(), rdbClient, "token")
	assert.NoError(t, err)
	assert.Equal(t, "18900001111", mobile)
}

TestLogin 函數(shù)非常簡(jiǎn)單,這得益于前期的準(zhǔn)備工作做的非常全面。

使用 go test 來(lái)執(zhí)行測(cè)試函數(shù):

$ go test -v                    
2023/07/26 20:48:12 github.com/testcontainers/testcontainers-go - Connected to docker: 
  Server Version: 20.10.21
  API Version: 1.41
  Operating System: Docker Desktop
  Total Memory: 7851 MB
2023/07/26 20:48:12 ?? Creating container for image docker.io/testcontainers/ryuk:0.5.1
2023/07/26 20:48:12 ? Container created: a261dc723001
2023/07/26 20:48:12 ?? Starting container: a261dc723001
2023/07/26 20:48:12 ? Container started: a261dc723001
2023/07/26 20:48:12 ?? Waiting for container id a261dc723001 image: docker.io/testcontainers/ryuk:0.5.1. Waiting for: &{Port:8080/tcp timeout:<nil> PollInterval:100ms}
2023/07/26 20:48:13 ?? Creating container for image redis:6.0.20-alpine
2023/07/26 20:48:13 ? Container created: 6420ead815a0
2023/07/26 20:48:13 ?? Starting container: 6420ead815a0
2023/07/26 20:48:13 ? Container started: 6420ead815a0
2023/07/26 20:48:13 ?? Waiting for container id 6420ead815a0 image: redis:6.0.20-alpine. Waiting for: &{timeout:<nil> Log:Ready to accept connections Occurrence:1 PollInterval:100ms}
=== RUN   TestLogin
--- PASS: TestLogin (0.01s)
PASS
2023/07/26 20:48:13 ?? Terminating container: 6420ead815a0
2023/07/26 20:48:13 ?? Container terminated: 6420ead815a0
ok      github.com/jianghushinian/test/db/redis 1.630s

測(cè)試通過(guò)。

總結(jié)

我們使用 testcontainers-go 包實(shí)現(xiàn)了在 Go 程序中啟動(dòng)一個(gè) Docker 容器,以此解決了集成測(cè)試中依賴外部 Redis 問(wèn)題。

可以發(fā)現(xiàn),Docker 非常適合集成測(cè)試,使用 Dokcer 來(lái)輔助集成測(cè)試是 Go 應(yīng)用程序集成測(cè)試的最佳實(shí)踐。而完善的集成測(cè)試,可以確保應(yīng)用程序的可靠性、可擴(kuò)展性和可維護(hù)性。

以上就是Golang使用Docker進(jìn)行集成測(cè)試的示例詳解的詳細(xì)內(nèi)容,更多關(guān)于Go Docker集成測(cè)試的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • go語(yǔ)言實(shí)現(xiàn)兩個(gè)協(xié)程交替打印

    go語(yǔ)言實(shí)現(xiàn)兩個(gè)協(xié)程交替打印

    這篇文章主要介紹了go語(yǔ)言實(shí)現(xiàn)兩個(gè)協(xié)程交替打印,文章主要分享了兩種方法使用兩個(gè)channel和使用一個(gè)channel,內(nèi)容介紹詳細(xì)具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-03-03
  • go語(yǔ)言代碼生成器code?generator使用示例介紹

    go語(yǔ)言代碼生成器code?generator使用示例介紹

    這篇文章主要為大家介紹了go語(yǔ)言代碼生成器code?generator的使用簡(jiǎn)單介紹,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-05-05
  • go語(yǔ)言beego框架分頁(yè)器操作及接口頻率限制示例

    go語(yǔ)言beego框架分頁(yè)器操作及接口頻率限制示例

    這篇文章主要為大家介紹了go語(yǔ)言beego框架分頁(yè)器操作使用示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪
    2022-04-04
  • golang切片內(nèi)存應(yīng)用技巧詳解

    golang切片內(nèi)存應(yīng)用技巧詳解

    這篇文章主要介紹了golang切片內(nèi)存應(yīng)用技巧詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • Golang 如何解析和生成json

    Golang 如何解析和生成json

    這篇文章主要介紹了Golang 如何解析和生成json,幫助大家更好的理解和學(xué)習(xí)golang,感興趣的朋友可以了解下
    2020-09-09
  • Go語(yǔ)言數(shù)據(jù)類型簡(jiǎn)單介紹

    Go語(yǔ)言數(shù)據(jù)類型簡(jiǎn)單介紹

    這篇文章主要介紹了Go語(yǔ)言數(shù)據(jù)類型簡(jiǎn)單介紹的相關(guān)資料,需要的朋友可以參考下
    2023-08-08
  • 一文帶你搞懂Golang依賴注入的設(shè)計(jì)與實(shí)現(xiàn)

    一文帶你搞懂Golang依賴注入的設(shè)計(jì)與實(shí)現(xiàn)

    在現(xiàn)代的 web 框架里面,基本都有實(shí)現(xiàn)了依賴注入的功能,可以讓我們很方便地對(duì)應(yīng)用的依賴進(jìn)行管理。今天我們來(lái)看看 go 里面實(shí)現(xiàn)依賴注入的一種方式,感興趣的可以了解一下
    2023-01-01
  • gORM操作MySQL的實(shí)現(xiàn)

    gORM操作MySQL的實(shí)現(xiàn)

    本文主要介紹了gORM操作MySQL的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-07-07
  • golang通用的grpc?http基礎(chǔ)開(kāi)發(fā)框架使用快速入門

    golang通用的grpc?http基礎(chǔ)開(kāi)發(fā)框架使用快速入門

    這篇文章主要為大家介紹了golang通用的grpc?http基礎(chǔ)開(kāi)發(fā)框架使用快速入門詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-09-09
  • gin項(xiàng)目部署到服務(wù)器并后臺(tái)啟動(dòng)的步驟

    gin項(xiàng)目部署到服務(wù)器并后臺(tái)啟動(dòng)的步驟

    本文主要介紹了gin項(xiàng)目部署到服務(wù)器并后臺(tái)啟動(dòng)的步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-02-02

最新評(píng)論

壤塘县| 确山县| 慈利县| 临江市| 香格里拉县| 阳西县| 朝阳区| 安阳市| 抚州市| 宁陵县| 保康县| 连州市| 上饶市| 武城县| 齐齐哈尔市| 安康市| 黔东| 佛教| 张家川| 浪卡子县| 长海县| 红河县| 华容县| 旌德县| 故城县| 南川市| 康保县| 昂仁县| 铜山县| 澄城县| 信阳市| 中超| 阳江市| 台北市| 建宁县| 潞西市| 德清县| 阜阳市| 罗江县| 波密县| 西吉县|