问题描述
编辑
正如已接受的答案中所指出的,这里的问题是在错误的方向上打字。我想将以下 github 问题添加为附件,因为除了下面的 @matt 答案外,它还为我提供了有用的信息:
https://github.com/golang/mock/issues/316#issuecomment-512043925
原帖
我是依赖项注入的新手,想在使用 couchbase go sdk 的模块上对其进行测试。为此,我需要接口来重现 Cluster 和 Bucket 结构。
在 Cluster 接口上,我需要 Bucket()
方法,它具有以下签名:
func (c *gocb.Cluster) Bucket(bucketName string) *gocb.Bucket
我还需要 Bucket 接口的以下两个方法:
func (b *gocb.Bucket) Collection(collectionName string) gocb.*Collection
func (b *gocb.Bucket) DefaultCollection() *gocb.Collection
棘手的部分是 Cluster 和 Bucket 方法都有指针接收器。这本身并不难,因为我知道如何单独模拟这些方法(您只需要使用指向实现接口的类型的指针)。
问题在于,其中一个 Cluster 方法需要返回一个实现 Bucket 接口的指针,因为它也有指针接收器方法。我尝试了很多组合,但每次我使用非模拟 *gocb.Cluster
值作为我的一个函数的参数时,它都会失败,因为集群实例上的 Bucket
方法没有被正确实现实例。
以下是我最近的尝试:
package deps
import (
"github.com/couchbase/gocb/v2"
)
// Database mocks the gocb.Cluster interface.
type Database interface {
Bucket(bucketName string) *Bucket
}
// Bucket mocks the gocb.Bucket interface.
type Bucket interface {
Collection(collectionName string) *gocb.Collection
DefaultCollection() *gocb.Collection
}
每当我尝试使用实际的 gocb.Cluster 值时,linter 都会返回以下错误:
// Database mocks the gocb.Cluster interface.
type Database interface {
Bucket(bucketName string) Bucket
}
这又给了我以下 lint 错误:
解决方法
我认为您缺少的关键概念是模拟对象必须与您模拟的对象的接口要求相匹配。这包括方法的参数和返回值。
type Database interface {
// Bucket(bucketName string) *Bucket // Wrong
Bucket(bucketName string) *gocb.Bucket // Correct
}
您仍然可以将 Database.Bucket
的返回值用作 deps.Bucket
,前提是您还正确模拟了该接口。
除非我遗漏了您的测试过程中的某些内容,否则这应该可以满足您的需求。
package main
import (
"github.com/couchbase/gocb/v2"
)
// Database mocks the gocb.Cluster interface.
type Database interface {
Bucket(bucketName string) *gocb.Bucket
}
// Bucket mocks the gocb.Bucket interface.
type Bucket interface {
Collection(collectionName string) *gocb.Collection
DefaultCollection() *gocb.Collection
}
func someFunc(db Database) *gocb.Bucket {
return db.Bucket("")
}
func anotherFunc(bucket Bucket) {
bucket.Collection("")
}
func main() {
var cluster *gocb.Cluster
bucket := someFunc(cluster)
anotherFunc(bucket)
}