在Golang中测试会触发os.Exit()的函数,可以使用os/exec包来创建子进程进行测试。以下是一个完整的示例:
package main
import (
"log"
"os"
"os/exec"
"syscall"
"testing"
)
func FatalFunc() {
log.Fatal("test")
}
func TestFatalFunc(t *testing.T) {
if os.Getenv("BE_CRASHER") == "1" {
FatalFunc()
return
}
// 创建子进程
cmd := exec.Command(os.Args[0], "-test.run=TestFatalFunc")
cmd.Env = append(os.Environ(), "BE_CRASHER=1")
// 执行命令并获取退出状态
err := cmd.Run()
if e, ok := err.(*exec.ExitError); ok {
// 检查退出码是否为1(log.Fatal的默认退出码)
if status, ok := e.Sys().(syscall.WaitStatus); ok {
if status.ExitStatus() != 1 {
t.Errorf("expected exit status 1, got %d", status.ExitStatus())
}
} else {
t.Error("failed to get exit status")
}
} else {
t.Error("expected process to exit with error")
}
}
另一种方法是使用testing.M进行更精细的控制:
package main
import (
"log"
"os"
"testing"
)
func TestMain(m *testing.M) {
// 设置环境变量来标识子进程
if os.Getenv("IN_SUBPROCESS") == "1" {
// 在子进程中执行测试
code := m.Run()
os.Exit(code)
}
// 在主测试进程中
os.Exit(runTests(m))
}
func runTests(m *testing.M) int {
// 运行正常的测试
return m.Run()
}
func TestFatalInSubprocess(t *testing.T) {
if os.Getenv("IN_SUBPROCESS") == "1" {
log.Fatal("test")
return
}
// 创建并运行子进程
cmd := exec.Command(os.Args[0], "-test.run=TestFatalInSubprocess")
cmd.Env = append(os.Environ(), "IN_SUBPROCESS=1")
err := cmd.Run()
// 验证退出状态
// ... 同上一个示例的验证逻辑
}
对于更复杂的场景,可以创建一个辅助函数来封装子进程测试:
func testExitFunc(t *testing.T, testFunc func(), expectedExitCode int) {
if os.Getenv("TEST_EXIT_FUNC") == "1" {
testFunc()
return
}
cmd := exec.Command(os.Args[0], "-test.run="+t.Name())
cmd.Env = append(os.Environ(), "TEST_EXIT_FUNC=1")
err := cmd.Run()
if e, ok := err.(*exec.ExitError); ok {
if status, ok := e.Sys().(syscall.WaitStatus); ok {
if status.ExitStatus() != expectedExitCode {
t.Errorf("expected exit status %d, got %d",
expectedExitCode, status.ExitStatus())
}
}
} else if err == nil {
t.Error("expected process to exit with error")
}
}
func TestMyFatalFunc(t *testing.T) {
testExitFunc(t, func() {
log.Fatal("error occurred")
}, 1)
}
这些方法通过在子进程中执行会触发os.Exit()的代码,避免了测试进程本身的退出,同时能够验证退出状态码是否符合预期。