Unit testing 当我移除fmt.Println()时,golang中的猴子修补失败

Unit testing 当我移除fmt.Println()时,golang中的猴子修补失败,unit-testing,go,monkeypatching,Unit Testing,Go,Monkeypatching,在编写测试时,我必须修补一个方法以检查是否调用了它,这是我的代码: import "fmt" type myStruct struct {} func (myObject *myStruct) firstMethod() { myObject.SecondMethod() } func (myObject *myStruct) SecondMethod() { fmt.Println("Inside the original SecondMethod") //test fai

在编写测试时,我必须修补一个方法以检查是否调用了它,这是我的代码:

import "fmt"

type myStruct struct {}

func (myObject *myStruct) firstMethod() {
    myObject.SecondMethod()
}
func (myObject *myStruct) SecondMethod() {
    fmt.Println("Inside the original SecondMethod") //test fails if I remove this
}
这就是测试:

import (
    "reflect"
    "testing"
    "github.com/bouk/monkey"
    "github.com/stretchr/testify/assert"
    "fmt"
)
func TestThatSecondMethodIsCalled(t *testing.T) {
    myObject := &myStruct{}

    wasCalled := false
    monkey.PatchInstanceMethod(
        reflect.TypeOf(myObject),
        "SecondMethod",
        func(*myStruct) {
            fmt.Println("Inside the replacement of SecondMethod")
            wasCalled = true
        },
    )

    myObject.firstMethod()
    assert.True(t, wasCalled)
}
如果我像这样运行测试,它将通过,但是如果我从SecondMethod中删除
fmt.Println()
,那么测试将失败(测试使用方法的原始主体,而不是修补的主体)


此外,如果从Goland使用调试,即使第二个方法有一个空体,测试也会通过。

< P>这是由编译器的内联优化导致的,添加<代码> -gcFLAGS=“-N-I”< /代码>将禁用它。

如果您使用像这样的猴子补丁,我不会真的认为测试是可靠的。如果您阅读该项目的自述文件,您将看到
Monkey有时在启用内联时无法修补函数
——另外请注意
Monkey不是线程安全的。或任何类型的保险箱。
。这是一个很好的实验,但必须有更好、更安全的方法来做你想做的事情。
github.com/bouk/monkey
依赖于逆向工程一种可能存在也可能不存在的代码生成模式:Go中的猴子补丁:正如你所发现的,它非常脆弱。更糟糕的是,它在测试时会给出误报和误报,在执行时会给出错误的结果。