package main
import (
"os"
"testing"
)
func TestMyAbstractFunctionAndExit(t *testing.T) {
var ok bool = false // The default value can be omitted :)
// Prepare testing
my_private_exit_function = func(c int) {
ok = true
}
// Run function
MyAbstractFunctionAndExit(1)
// Check
if ok == false {
t.Errorf("Error in AbstractFunction()")
}
// Restore if need
my_private_exit_function = os.Exit
}
type PatchedOSExit struct {
Called bool
CalledWith int
patchFunc *mpatch.Patch
}
func PatchOSExit(t *testing.T, mockOSExitImpl func(int)) *PatchedOSExit {
patchedExit := &PatchedOSExit{Called: false}
patchFunc, err := mpatch.PatchMethod(os.Exit, func(code int) {
patchedExit.Called = true
patchedExit.CalledWith = code
mockOSExitImpl(code)
})
if err != nil {
t.Errorf("Failed to patch os.Exit due to an error: %v", err)
return nil
}
patchedExit.patchFunc = patchFunc
return patchedExit
}
func (p *PatchedOSExit) Unpatch() {
_ = p.patchFunc.Unpatch()
}
你可以使用上面的代码如下:
func NewSampleApplication() {
os.Exit(101)
}
func Test_NewSampleApplication_OSExit(t *testing.T) {
// Prepare mock setup
fakeExit := func(int) {}
p := PatchOSExit(t, fakeExit)
defer p.Unpatch()
// Call the application code
NewSampleApplication()
// Assert that os.Exit gets called
if p.Called == false {
t.Errorf("Expected os.Exit to be called but it was not called")
return
}
// Also, Assert that os.Exit gets called with the correct code
expectedCalledWith := 101
if p.CalledWith != expectedCalledWith {
t.Errorf("Expected os.Exit to be called with %d but it was called with %d", expectedCalledWith, p.CalledWith)
return
}
}
7条答案
按热度按时间smdnsysy1#
Andrew Gerrand(Go团队的核心成员之一)的presentation展示了如何做到这一点。
给定一个函数(在
main.go
中)下面是测试方法(通过
main_test.go
):该代码所做的是通过
exec.Command
在单独的进程中再次调用go test
,将执行限制为TestCrasher
测试(通过-test.run=TestCrasher
开关)。它还通过环境变量传入一个标志(BE_CRASHER=1
),第二次调用检查该值,如果设置了该值,则调用被测系统,然后立即返回,以防止运行到无限循环中。因此,我们被退回到原始调用站点,现在可以验证实际的退出代码。来源:Andrew演示文稿的第23张幻灯片。第二张幻灯片也包含presentation's video的链接。他谈到了47:09的子流程测试。
hs1ihplo2#
我使用bouk/monkey来实现:
monkey在处理这类工作、故障注入和其他困难任务时非常强大。
7uhlpewt3#
我认为如果不从外部(使用
exec.Command
)模拟测试过程,就无法测试实际的os.Exit
。也就是说,你可以通过创建一个接口或函数类型,然后在测试中使用noop实现来实现你的目标:
Go Playground
cedebl8k4#
你不能,你必须使用
exec.Command
并测试返回值。hc8w905p5#
测试代码:
测试代码:
d4so4syb6#
为了测试类似
os.Exit
的场景,我们可以使用https://github.com/undefinedlabs/go-mpatch沿着下面的代码。这可以确保您的代码保持整洁,可读性和可维护性。你可以使用上面的代码如下:
我还添加了一个链接到Playground:https://go.dev/play/p/FA0dcwVDOm7
js81xvg67#
在我的代码中我刚刚使用了
然后把它叫做:
这样
doomedOrNot
就可以很容易地测试。