在 golang 中测试第三方包
Testing 3rd party package in golang
我是 golang 的新手,正在尝试使用来自 https://github.com/huandu/facebook 的 facebook 包编写一个简单的学习应用程序。
我能够拿到包裹并连接到 facebook 并点击 facebook API。这很好,但我关心的是测试。
起初我只是调用该方法并在其中创建一个 facebook 对象。然后经过一些研究,我尝试传入我想模拟的 facebook 方法。意识到我需要多种方法,我相信传递接口是正确的方法。
所以我尝试创建包将实现的接口。
type IFbApp interface {
ExchangeToken(string) (string, int, error)
Session(string) IFbSession
}
type MyFbApp struct{}
func (myFbApp *MyFbApp) ExchangeToken(token string) (string, int, error) {
return myFbApp.ExchangeToken(token)
}
func (myFbApp *MyFbApp) Session(token string) IFbSession {
return myFbApp.Session(token)
}
type IFbSession interface {
User() (string, error)
Get(string, map[string]interface{}) (map[string]interface{}, error)
}
type MyFbSession struct{}
func (myFbSession *MyFbSession) User() (string, error) {
return myFbSession.User()
}
func (myFbSession *MyFbSession) Get(path string, params map[string]string) (map[string]string, error) {
return myFbSession.Get(path, params)
}
func SomeMethod() {
Facebook(fb.New("appId", "appSecret")); // fb calls package
}
func Facebook(fbI IFbApp) {
fbI.ExchangeToken("sometokenhere");
}
我无法编译此代码,因为出现错误
cannot use facebook.New("appId", "appSecret") (type *facebook.App) as type IFbApp in argument to Facebook:
*facebook.App does not implement IFbApp (wrong type for Session method)
have Session(string) *facebook.Session
want Session(string) IFbSession
将 IFbSession 切换为 *facebook.Session 当然可以编译,但我还需要从 Session 结构中模拟方法。
我的计划是创建模拟结构,在我的 test.go 文件中实现我的接口,并将其传递给被测方法。这是正确的方法吗?
我想尽可能保持纯 golang,远离 mocking 框架。
谢谢。
您可以为 fb.App 实现包装器并将 Session 方法重写为 return IFbSession 而不是 Facebook.Session。
package main
import fb "github.com/huandu/facebook"
type IFbApp interface {
ExchangeToken(string) (string, int, error)
Session(string) IFbSession
}
type MockFbApp struct {
IFbApp
}
func (myFbApp *MockFbApp) ExchangeToken(token string) (string, int, error) {
return "exchangetoken", 1, nil
}
func (myFbApp *MockFbApp) Session(token string) IFbSession {
return &MyFbSession{}
}
type IFbSession interface {
User() (string, error)
Get(string, fb.Params) (fb.Result, error)
}
type MyFbSession struct {
IFbSession
}
func (myFbSession *MyFbSession) User() (string, error) {
return "userid", nil
}
func (myFbSession *MyFbSession) Get(path string, params fb.Params) (fb.Result, error) {
return fb.Result{}, nil
}
type RealApp struct {
*fb.App
}
func (myFbApp *RealApp) Session(token string) IFbSession {
return myFbApp.App.Session(token)
}
func SomeMethod() {
Facebook(&MockFbApp{})
Facebook(&RealApp{fb.New("appId", "appSecret")})
}
func Facebook(fbI IFbApp) {
fbI.ExchangeToken("sometokenhere")
fbI.Session("session")
}
func main() {
SomeMethod()
}
我是 golang 的新手,正在尝试使用来自 https://github.com/huandu/facebook 的 facebook 包编写一个简单的学习应用程序。
我能够拿到包裹并连接到 facebook 并点击 facebook API。这很好,但我关心的是测试。
起初我只是调用该方法并在其中创建一个 facebook 对象。然后经过一些研究,我尝试传入我想模拟的 facebook 方法。意识到我需要多种方法,我相信传递接口是正确的方法。
所以我尝试创建包将实现的接口。
type IFbApp interface {
ExchangeToken(string) (string, int, error)
Session(string) IFbSession
}
type MyFbApp struct{}
func (myFbApp *MyFbApp) ExchangeToken(token string) (string, int, error) {
return myFbApp.ExchangeToken(token)
}
func (myFbApp *MyFbApp) Session(token string) IFbSession {
return myFbApp.Session(token)
}
type IFbSession interface {
User() (string, error)
Get(string, map[string]interface{}) (map[string]interface{}, error)
}
type MyFbSession struct{}
func (myFbSession *MyFbSession) User() (string, error) {
return myFbSession.User()
}
func (myFbSession *MyFbSession) Get(path string, params map[string]string) (map[string]string, error) {
return myFbSession.Get(path, params)
}
func SomeMethod() {
Facebook(fb.New("appId", "appSecret")); // fb calls package
}
func Facebook(fbI IFbApp) {
fbI.ExchangeToken("sometokenhere");
}
我无法编译此代码,因为出现错误
cannot use facebook.New("appId", "appSecret") (type *facebook.App) as type IFbApp in argument to Facebook:
*facebook.App does not implement IFbApp (wrong type for Session method)
have Session(string) *facebook.Session
want Session(string) IFbSession
将 IFbSession 切换为 *facebook.Session 当然可以编译,但我还需要从 Session 结构中模拟方法。
我的计划是创建模拟结构,在我的 test.go 文件中实现我的接口,并将其传递给被测方法。这是正确的方法吗?
我想尽可能保持纯 golang,远离 mocking 框架。
谢谢。
您可以为 fb.App 实现包装器并将 Session 方法重写为 return IFbSession 而不是 Facebook.Session。
package main
import fb "github.com/huandu/facebook"
type IFbApp interface {
ExchangeToken(string) (string, int, error)
Session(string) IFbSession
}
type MockFbApp struct {
IFbApp
}
func (myFbApp *MockFbApp) ExchangeToken(token string) (string, int, error) {
return "exchangetoken", 1, nil
}
func (myFbApp *MockFbApp) Session(token string) IFbSession {
return &MyFbSession{}
}
type IFbSession interface {
User() (string, error)
Get(string, fb.Params) (fb.Result, error)
}
type MyFbSession struct {
IFbSession
}
func (myFbSession *MyFbSession) User() (string, error) {
return "userid", nil
}
func (myFbSession *MyFbSession) Get(path string, params fb.Params) (fb.Result, error) {
return fb.Result{}, nil
}
type RealApp struct {
*fb.App
}
func (myFbApp *RealApp) Session(token string) IFbSession {
return myFbApp.App.Session(token)
}
func SomeMethod() {
Facebook(&MockFbApp{})
Facebook(&RealApp{fb.New("appId", "appSecret")})
}
func Facebook(fbI IFbApp) {
fbI.ExchangeToken("sometokenhere")
fbI.Session("session")
}
func main() {
SomeMethod()
}