GO UT

参考如下golang ut写法 -- convey框架 + gomonkey 框架:

func TestEnvCheck(t *testing.T) {
	Convey("test EnvCheck", t, func() {
		zapLogger, _ := zap.NewProduction()
		logger := zapLogger.Sugar()
		patches := gomonkey.NewPatches()
		param := EnvCheckParamInfo{
			StreamNo:  "envCheck_111",
			MaterIp:   "gdb-manager-test.gdb",
			IAPort:    "8021",
			RdbPasswd: "*****",
			ApiType:   "https",
		}
		Convey("test 1: envCheck success", func() {
			defer patches.Reset()
			patches.ApplyFunc(agentConfig.LocalExecutionCommand, func(request agentConfig.CmdExecRequest) agentConfig.CmdExecResult {
				return agentConfig.CmdExecResult{ReturnCode: agentConfig.TaskSuccessCode}
			})
			_, err := EnvCheck(param, logger)
			So(err, ShouldBeNil)
		})
		Convey("test 2: envCheck failed", func() {
			defer patches.Reset()
			patches.ApplyFunc(agentConfig.LocalExecutionCommand, func(request agentConfig.CmdExecRequest) agentConfig.CmdExecResult {
				return agentConfig.CmdExecResult{ReturnCode: agentConfig.TaskFailCode, ErrorMsg: "test error"}
			})
			_, err := EnvCheck(param, logger)
			So(err, ShouldNotBeNil)
		})
	})
}
对如下文件写ut:
1. 两层convey结构
2. 针对os.ReadFile 进行mock,返回测试需要的数据

package agentApis

import (
	"Operator/cmd/operator-agent/app/agentConfig"
	"time"
)

// OperatorAgentTask 表示OperatorAgent要执行的任务
type OperatorAgentTask struct {
	TaskID    string                `json:"taskID"`    // 任务ID
	TaskType  agentConfig.AgentTask `json:"taskType"`  // 任务类型
	TaskParam interface{}           `json:"taskParam"` // 任务参数
}

// AgentTaskResult OperatorAgent任务结果
type AgentTaskResult struct {
	TaskID     string                `json:"taskID"`     // 任务ID,格式taskType_timestamp
	TaskType   agentConfig.AgentTask `json:"taskType"`   // 任务类型
	TaskParam  interface{}           `json:"taskParam"`  // 任务参数
	TaskCode   int                   `json:"taskCode"`   // 任务返回码,0成功,2失败, 1任务ID不存在
	TaskStatus string                `json:"taskStatus"` // 任务状态:进行中、成功或失败
	TaskResult interface{}           `json:"taskResult"` // 任务结果
	ErrorMsg   string                `json:"errorMsg"`   // 任务报错
	StartTime  time.Time             `json:"startTime"`  // 任务起始时间
	EndTime    time.Time             `json:"endTime"`    // 任务结束时间
}


package cacheUtils

import (
	"Operator/cmd/operator-agent/app/agentApis"
	"Operator/cmd/operator-agent/app/agentConfig"
	gdberrors "Operator/pkg/utils/errors"
	"context"
	"encoding/json"
	"fmt"
	"go.uber.org/zap"
	"os"
	"path/filepath"
	"sync"
	"time"
)

type FileCache struct {
	mu          sync.RWMutex
	TaskResults map[string]*agentApis.AgentTaskResult // 缓存
	logger      *zap.SugaredLogger                    // 日志
	filePath    string
}

// recoverFromFile 从本地json文件读取
func (f *FileCache) recoverFromFile() error {
	if f.filePath == "" {
		return nil
	}
	f.mu.Lock()
	defer f.mu.Unlock()

	data, err := os.ReadFile(f.filePath)
	if err != nil {
		return err
	}
	var tempCache map[string]*agentApis.AgentTaskResult
	if err := json.Unmarshal(data, &tempCache); err != nil {
		return gdberrors.NewBaseError(gdberrors.JsonErr, fmt.Sprintf("parse json error %v", err))
	}

	for taskId, taskInfo := range tempCache {
		f.logger.Infof("[recoverFromFile] taskId %v", taskId)
		if taskInfo.TaskStatus == agentConfig.TaskProcessStatus {
			taskInfo.TaskStatus = agentConfig.TaskFailedStatus
			taskInfo.ErrorMsg = "Pod异常退出,任务中断"
			taskInfo.EndTime = time.Time{}
		}
	}
	f.TaskResults = tempCache

	return nil
}



要求:

  1. 两层 Convey 结构:

外层:test saveToFileLocked

内层:10个不同的测试场景

  1. 使用 gomonkey mock 多个基础函数:

os.Stat - 模拟目录检查

os.MkdirAll - 模拟目录创建

json.MarshalIndent - 模拟 JSON 序列化

os.WriteFile - 模拟文件写入

os.Rename - 模拟文件重命名
...

  1. 覆盖多种测试场景:

空文件路径

目录不存在且创建成功

目录不存在且创建失败

目录检查出错(非"不存在"错误)

JSON 序列化失败

文件写入失败

文件重命名失败

正常保存(复杂数据)

...

posted @ 2025-12-29 08:16  静水深耕,云停风驻  阅读(23)  评论(0)    收藏  举报