如何使用相互依赖的接口方法模拟结构
How to mock structs with interdependent interface methods
我在为一个相当常见的 use-case/pattern.
用 Go 编写单元测试时遇到了问题
想象一下,如果你愿意,是这样的:
package main
type Resource struct {
name string
}
type ResourceManager interface {
GetResource(id string) (*Resource, error)
GetAllResources() ([]*Resource, error)
}
type ResourceManagerImpl struct {
}
func (r *ResourceManagerImpl) GetResource(id string) (*Resource, error) {
resource := &Resource{}
var err error
// fetch resource.
// ...
return resource, err
}
func (r *ResourceManagerImpl) GetAllResources() ([]*Resource, error) {
var resources []*Resource
var err error
// for _, id := range ids {
// resource = r.GetResource(id)
// resources = append(resources, resource)
// }
return resources, err
}
让 GetAllResources
根据需要重复调用 GetResource
是一种常见的模式。
我可以使用 gomock
或 testify
来测试 GetResource
的所有排列。但是,在测试 GetAllResource
时,我想模拟 GetResource
。否则,测试将变成一场噩梦。如果 Java 使用部分模拟,这就是 easymock
或 mockito
中的做法。但是,尚不清楚如何在 Golang 中实现相同的目标。
具体来说,我找不到如何部分模拟 struct
。大多数建议都围绕打破这样的 struct
展开,但在这种情况下,struct
已经处于最低限度。为了测试而不破坏 ResourceManager
接口(分为单个和多个)似乎是一个公平的要求,因为这没有多大意义,充其量是笨拙的,并且不会像更多这样的方法那样很好地扩展进入界面
遇到这种情况我是这样处理的:
func (r *ResourceManagerImpl) GetAllResources() ([]*Resource, error) {
return getAllResources(r)
}
func getAllResources(r ResourceManager) ([]*Resource,error) {
...
}
然后用模拟的 r
测试 getAllResources
而不是 GetAllResources
。如果你遇到从代码中调用 GetAllResources
的情况,你必须模拟 GetAllResources
,你可以这样做:
var getAllResources=func(r ResourceManager) ([]*Resource,error) {
...
}
并将 getAllResources 分配给测试实例。
我在为一个相当常见的 use-case/pattern.
用 Go 编写单元测试时遇到了问题想象一下,如果你愿意,是这样的:
package main
type Resource struct {
name string
}
type ResourceManager interface {
GetResource(id string) (*Resource, error)
GetAllResources() ([]*Resource, error)
}
type ResourceManagerImpl struct {
}
func (r *ResourceManagerImpl) GetResource(id string) (*Resource, error) {
resource := &Resource{}
var err error
// fetch resource.
// ...
return resource, err
}
func (r *ResourceManagerImpl) GetAllResources() ([]*Resource, error) {
var resources []*Resource
var err error
// for _, id := range ids {
// resource = r.GetResource(id)
// resources = append(resources, resource)
// }
return resources, err
}
让 GetAllResources
根据需要重复调用 GetResource
是一种常见的模式。
我可以使用 gomock
或 testify
来测试 GetResource
的所有排列。但是,在测试 GetAllResource
时,我想模拟 GetResource
。否则,测试将变成一场噩梦。如果 Java 使用部分模拟,这就是 easymock
或 mockito
中的做法。但是,尚不清楚如何在 Golang 中实现相同的目标。
具体来说,我找不到如何部分模拟 struct
。大多数建议都围绕打破这样的 struct
展开,但在这种情况下,struct
已经处于最低限度。为了测试而不破坏 ResourceManager
接口(分为单个和多个)似乎是一个公平的要求,因为这没有多大意义,充其量是笨拙的,并且不会像更多这样的方法那样很好地扩展进入界面
遇到这种情况我是这样处理的:
func (r *ResourceManagerImpl) GetAllResources() ([]*Resource, error) {
return getAllResources(r)
}
func getAllResources(r ResourceManager) ([]*Resource,error) {
...
}
然后用模拟的 r
测试 getAllResources
而不是 GetAllResources
。如果你遇到从代码中调用 GetAllResources
的情况,你必须模拟 GetAllResources
,你可以这样做:
var getAllResources=func(r ResourceManager) ([]*Resource,error) {
...
}
并将 getAllResources 分配给测试实例。