go test 的内联问题

写单测的时候遇到一个问题,在使用 gomonkey 进行打桩时,使用 gland 的 debug 运行测试时,测试程序正常跑通,而使用 run 或者命令行运行 go test -v 时会在打桩函数调用的时候报错 invalid memory address or nil pointer dereference

单测代码

func TestLogin(t *testing.T) {
        // 初始化 dao 层
    userDao := &daoUser.UserDao{}
        // 初始化 service 层
    entity := &LoginService{}

    Convey("GetUserByUsername", t, func() {
        Convey("Should be success", func() {
                        // 给 GetByUsername 函数打桩,指定返回值
            patches := ApplyMethod(reflect.TypeOf(UserDao), "GetByUsername",
                func(*daoUser.UserDao, string) (*daoUser.User, error) {
                    return &daoUser.User{
                        ID:       1,
                        Username: "weirwei",
                        Password: "123456",
                    }, nil
                })
            defer patches.Reset()
                        // 测试 Login
            res, err := entity.Login("weirwei", "123456")
                        // 断言
            So(err, ShouldBeNil)
            So(res, ShouldBeTrue)
        })
        })
}

问题分析

查看 rundebug的命令

run
/usr/local/go/bin/go test -c -o /private/var/folders/1q/llslx_n95d1brs7hq2drxjjw0000gn/T/___1go_test_gin_study_service_svUser gin-study/service/svUser

debug
/usr/local/go/bin/go test -c -o /private/var/folders/1q/llslx_n95d1brs7hq2drxjjw0000gn/T/___go_test_gin_study_service_svUser -gcflags all=-N -l gin-study/service/svUser

很明显就能发现 debugrun多了 -gcflags all=-N -l,这个就是禁用内联的选项

内联(inlining):粗暴的来说,就是将函数内容复制到函数调用的地方,减少了函数调用的开支,但一定程度上会增加程序的代码量,占用更多的内存。

这么看就很明显了,本来打桩后 GetUserByUsername 会直接返回给定的结果,不走 dao 层的实际代码,但是 go 在编译过程中会进行内联优化,将 dao 层的代码直接”复制”过来,绕过了测试桩。而在本段测试代码中并没有对 dao 层进行相关配置及初始化,导致代码在执行时出现错误。

Original: https://www.cnblogs.com/weirwei/p/14638060.html
Author: weirwei
Title: go test 的内联问题

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/591868/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球