golang编写UT:applyFunc和applyMethod区别
在 GoConvey(github.com/smartystreets/goconvey/convey)中,ApplyFunc 和 ApplyMethod 都用于 mock(模拟)函数或方法,主要区别在于它们的作用对象不同:
| 函数 | 作用对象 | 用途 |
|---|---|---|
ApplyFunc | 普通函数 | Mock 一个全局函数或包级函数 |
ApplyMethod | 结构体方法 | Mock 某个结构体的实例方法 |
1️⃣ ApplyFunc 用于 Mock 普通函数
ApplyFunc 用于替换**包级函数(普通全局函数)**的实现,例如:
package main
import (
"fmt"
"testing"
. "github.com/smartystreets/goconvey/convey"
"github.com/smartystreets/goconvey/convey/gomock"
)
// 目标函数
func GetData() string {
return "Real Data"
}
func TestApplyFunc(t *testing.T) {
Convey("Mock GetData function", t, func() {
// Mock GetData,使其返回 "Mocked Data"
reset := gomock.ApplyFunc(GetData, func() string {
return "Mocked Data"
})
defer reset() // 确保测试结束后恢复原函数
So(GetData(), ShouldEqual, "Mocked Data") // 断言函数返回值
})
}
🔹 原理:ApplyFunc(GetData, mockImplementation) 拦截了 GetData 函数的调用,并让它返回 "Mocked Data"。
2️⃣ ApplyMethod 用于 Mock 结构体方法
ApplyMethod 用于 mock 某个结构体实例的方法,例如:
package main
import (
"testing"
. "github.com/smartystreets/goconvey/convey"
"github.com/smartystreets/goconvey/convey/gomock"
)
// 结构体
type UserService struct{}
func (u *UserService) GetUserName() string {
return "Real User"
}
func TestApplyMethod(t *testing.T) {
Convey("Mock UserService.GetUserName method", t, func() {
// Mock 结构体的 GetUserName 方法
reset := gomock.ApplyMethod((*UserService)(nil), "GetUserName", func(_ *UserService) string {
return "Mocked User"
})
defer reset() // 确保测试结束后恢复原方法
service := &UserService{}
So(service.GetUserName(), ShouldEqual, "Mocked User") // 断言方法返回值
})
}
🔹 原理:
ApplyMethod((*UserService)(nil), "GetUserName", mockImplementation)拦截了 所有UserService实例的GetUserName方法,使其返回"Mocked User"。
🎯 总结
| 方法 | Mock 目标 | 使用示例 |
|---|---|---|
ApplyFunc | 普通函数 | ApplyFunc(GetData, mockFunc) |
ApplyMethod | 结构体方法 | ApplyMethod((*UserService)(nil), "MethodName", mockFunc) |
ApplyFunc适用于:Mock 全局函数ApplyMethod适用于:Mock 某个结构体的实例方法
🚀 什么时候用?
- 当你在 单元测试 里,需要 隔离依赖的外部函数 或 方法,避免真实逻辑执行,或者控制返回值时,可以使用
ApplyFunc或ApplyMethod来 Mock 这些函数/方法。
