🎭 Mock 接口
pkg/composerutils/mock 提供接口化的 Mock 实现,是整个项目可测试性的基石。通过定义 CommandExecutor、FileSystemHelper、DownloadHelper、RuntimeInfo 等接口,上层模块可在测试中替换真实系统调用。
接口与实现清单
| 接口 | 默认实现 | Mock 实现 | 用途 |
|---|---|---|---|
CommandExecutor | DefaultCommandExecutor | MockCommandExecutor | 执行系统命令 |
FileSystemHelper | DefaultFileSystemHelper | MockFileSystemHelper | 文件系统操作 |
DownloadHelper | (由调用方实现) | MockDownloadHelper | 文件下载 |
RuntimeInfo | — | MockRuntime | 运行时环境(GOOS/GOARCH) |
CommandExecutor
go
type CommandExecutor interface {
Execute(name string, args ...string) ([]byte, error)
}DefaultCommandExecutor用exec.Command执行真实命令。MockCommandExecutor按「命令+参数」键返回预设结果。
MockCommandExecutor
go
func NewMockCommandExecutor() *MockCommandExecutor
func (e *MockCommandExecutor) SetCommandResult(name string, args []string, output []byte, err error)
func (e *MockCommandExecutor) Execute(name string, args ...string) ([]byte, error)go
mock := NewMockCommandExecutor()
mock.SetCommandResult("composer", []string{"--version"}, []byte("Composer 2.7.0"), nil)
out, err := mock.Execute("composer", "--version")
fmt.Println(string(out)) // Composer 2.7.0未匹配会报错
Execute 找不到预设结果时返回 未找到模拟命令结果: <key>,确保测试不会误发真实命令。
FileSystemHelper
go
type FileSystemHelper interface {
CreateFile(path string, content []byte, perm os.FileMode) error
CheckWritePermission(path string) error
EnsureDirectoryExists(path string) error
RemoveFile(path string) error
}MockFileSystemHelper 用函数字段实现每个方法,默认全部返回 nil,可按需替换:
go
func NewMockFileSystemHelper() *MockFileSystemHelper
type MockFileSystemHelper struct {
CreateFileFunc func(path string, content []byte, perm os.FileMode) error
CheckWritePermissionFunc func(path string) error
EnsureDirectoryExistsFunc func(path string) error
RemoveFileFunc func(path string) error
}go
mockFS := NewMockFileSystemHelper()
mockFS.CheckWritePermissionFunc = func(path string) error {
return errors.New("模拟无权限")
}
_ = mockFS.CheckWritePermission("/root")DownloadHelper
go
type DownloadHelper interface {
DownloadFile(url string, target string, config interface{}) error
}MockDownloadHelper 同样用 DownloadFileFunc 字段,默认成功。
MockRuntime
模拟运行时环境,用于测试平台相关逻辑而无需真实切换 OS。
go
type RuntimeInfo struct {
GOOS string
GOARCH string
}
func NewMockRuntime() *MockRuntime
func (r *MockRuntime) SetOS(os string)
func (r *MockRuntime) GetOS() string
func (r *MockRuntime) SetArch(arch string)
func (r *MockRuntime) GetArch() stringgo
rt := NewMockRuntime()
rt.SetOS("darwin")
rt.SetArch("arm64")
fmt.Println(rt.GetOS(), rt.GetArch()) // darwin arm64设计意义
为什么用接口 + Mock
pkg/composer 的 234 个方法都执行本地 composer 二进制,测试时若真跑 composer 会极慢且依赖环境。通过 CommandExecutor 接口注入 Mock,测试可在毫秒级完成、450+ 用例全量隔离运行。这正是项目「测试完善」的基础。
进阶
pkg/composer自己还有一套更上层的 Mock:SetupMockOutput/SetupMockOutputAdvanced,见 Composer 核心。- 测试辅助工具见 测试辅助。
- 架构层面的可测试性讨论见 可测试性设计。