🎭 Mock Interfaces
pkg/composerutils/mock provides interface-based mock implementations, the cornerstone of the project's testability. By defining interfaces like CommandExecutor, FileSystemHelper, DownloadHelper, RuntimeInfo, upper modules can replace real system calls in tests.
Interface and Implementation List
| Interface | Default Implementation | Mock Implementation | Usage |
|---|---|---|---|
CommandExecutor | DefaultCommandExecutor | MockCommandExecutor | Execute system commands |
FileSystemHelper | DefaultFileSystemHelper | MockFileSystemHelper | File system operations |
DownloadHelper | (implemented by caller) | MockDownloadHelper | File download |
RuntimeInfo | — | MockRuntime | Runtime environment (GOOS/GOARCH) |
CommandExecutor
type CommandExecutor interface {
Execute(name string, args ...string) ([]byte, error)
}DefaultCommandExecutorexecutes real commands usingexec.Command.MockCommandExecutorreturns preset results by "command+args" key.
MockCommandExecutor
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)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.0Unmatched commands error
Execute returns 未找到模拟命令结果: <key> (mock command result not found) when no preset result is found, ensuring tests won't accidentally send real commands.
FileSystemHelper
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 implements each method via function fields, all default to returning nil, can be replaced as needed:
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
}mockFS := NewMockFileSystemHelper()
mockFS.CheckWritePermissionFunc = func(path string) error {
return errors.New("mock no permission")
}
_ = mockFS.CheckWritePermission("/root")DownloadHelper
type DownloadHelper interface {
DownloadFile(url string, target string, config interface{}) error
}MockDownloadHelper also uses DownloadFileFunc field, defaults to success.
MockRuntime
Mocks runtime environment, used to test platform-specific logic without real OS switching.
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() stringrt := NewMockRuntime()
rt.SetOS("darwin")
rt.SetArch("arm64")
fmt.Println(rt.GetOS(), rt.GetArch()) // darwin arm64Design Significance
Why interface + Mock
pkg/composer's 234 methods all execute local composer binary. Running real composer in tests would be extremely slow and environment-dependent. By injecting Mock via CommandExecutor interface, tests complete in milliseconds, 450+ cases all run isolated. This is the foundation of the project's "comprehensive testing".
Advanced
pkg/composerhas its own upper-level mock:SetupMockOutput/SetupMockOutputAdvanced, see Composer Core.- Test utilities see Test Utilities.
- Architecture-level testability discussion see Testability Design.