英文:
Interface use in golang for mocking third party libraries
问题
我正在尝试使用VMware vSphere API客户端(govmomi)创建一个简单的模拟来对一些代码进行单元测试,但是我在寻找可用模式方面遇到了困难。
客户端库的一个简单用例是检索vSphere集群的安装许可证:
vclient, err := govmomi.NewClient(*vcurl, true)
if err != nil {
return err
}
lic, err := vclient.LicenseManager().ListLicenses()
NewClient()
返回一个指向 Client
结构的指针,Client.LicenseManager()
返回一个 LicenseManager
结构的实例,LicenseManager.ListLicenses()
返回一个包含许可证信息的结构切片。作为一个有Python背景的人,我通常会对 LicenseManager
上的 ListLicenses()
方法进行模拟,但是我似乎无法找到Go中的可比模式或方法。
到目前为止,我尝试创建一个包含govmomi Client
结构作为匿名成员的包装结构 VCenterClient
,以及一个用于创建具有模拟逻辑的包装结构新实例的“构造函数” NewVCenter()
:
import (
"net/url"
"github.com/vmware/govmomi"
"github.com/vmware/govmomi/vim25/types"
)
type VCenterClient struct {
VCenterClientInterface
}
type VCenterClientInterface interface {
LicenseManager() LicenseManager
}
type LicenseManager interface {
ListLicenses() ([]types.LicenseManagerLicenseInfo, error)
}
type VCenterClientMock struct{}
type LicenseManagerMock struct{}
func (v *VCenterClientMock) LicenseManager() LicenseManager {
return LicenseManagerMock{}
}
func (l LicenseManagerMock) ListLicenses() ([]types.LicenseManagerLicenseInfo, error) {
return make([]types.LicenseManagerLicenseInfo, 0), nil
}
func NewVCenterClient(uri string, mock bool) *VCenterClient {
if mock {
return &VCenterClient{&VCenterClientMock{}}
}
vcurl, _ := url.Parse(uri)
vclient, _ := govmomi.NewClient(*vcurl, true)
return &VCenterClient{vclient}
}
...但是我在使用接口来正确抽象govmomi库中的嵌套结构方面遇到了困难。我知道上述代码不起作用,因为 govmomi.LicenseManager()
返回类型为 govmomi.LicenseManager
的结构,而我的 VCenterClientInterface.LicenseManager()
方法返回类型为 LicenseManager
的接口。然而,我在寻找替代方案方面遇到了困难。
如果能在这种情况下提供更好的设计模式或正确使用接口的帮助,将不胜感激。
英文:
I'm trying to create a simple mock for unit testing some code using the VMware vSphere API client - govmomi - but I'm having trouble finding a usable pattern.
A simple use case for the client library would be to retrieve the installed licenses for a vSphere cluster:
vclient, err := govmomi.NewClient(*vcurl, true)
if err != nil {
return err
}
lic, err := vclient.LicenseManager().ListLicenses()
NewClient()
returns a pointer to a Client structure, Client.LicenseManager()
returns an instance of a LicenseManager structure, and LicenseManager.ListLicenses()
returns a slice of structures containing the license info. Coming from a Python background, I'd usually monkey patch the ListLicenses()
method on LicenseManger
for a mock, but I can't seem to come up with a comparable pattern or methodology in Go.
To this point, I've tried creating a wrapper structure VCenterClient
with the govmomi Client
structure as an anonymous member and a "constructor" function NewVCenter()
to create new instances of the wrapper structure with logic for mocks:
import (
"net/url"
"github.com/vmware/govmomi"
"github.com/vmware/govmomi/vim25/types"
)
type VCenterClient struct {
VCenterClientInterface
}
type VCenterClientInterface interface {
LicenseManager() LicenseManager
}
type LicenseManager interface {
ListLicenses() ([]types.LicenseManagerLicenseInfo, error)
}
type VCenterClientMock struct{}
type LicenseManagerMock struct{}
func (v *VCenterClientMock) LicenseManager() LicenseManager {
return LicenseManagerMock{}
}
func (l LicenseManagerMock) ListLicenses() ([]types.LicenseManagerLicenseInfo, error) {
return make([]types.LicenseManagerLicenseInfo, 0), nil
}
func NewVCenterClient(uri string, mock bool) *VCenterClient {
if mock {
return &VCenterClient{&VCenterClientMock{}}
}
vcurl, _ := url.Parse(uri)
vclient, _ := govmomi.NewClient(*vcurl, true)
return &VCenterClient{vclient}
}
...but I having trouble using interfaces to properly abstract the nested structures in the govmomi library. I know the above will not work as govmomi.LicenseManager()
returns a structure of type govmomi.LicenseManager
and my VCenterClientInterface.LicenseManager()
method returns an interface of type LicenseManager
. However, I'm struggling to find an alternative.
Any help on a better design pattern or proper use of interfaces in this case would be much appreciated.
答案1
得分: 2
这个库是一个SOAP客户端(http://godoc.org/github.com/vmware/govmomi/vim25/soap#Client)。在HTTP层面上使用net/http/httptest(http://golang.org/pkg/net/http/httptest/)进行抽象,或者使用自己的HTTPRoundtripper来模拟响应。
英文:
This library is a SOAP client (http://godoc.org/github.com/vmware/govmomi/vim25/soap#Client). Abstract at the HTTP layer with net/http/httptest (http://golang.org/pkg/net/http/httptest/) or by using your own HTTPRoundtripper to mock the response.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论