-1

编辑

正如在接受的答案中指出的那样,这里的问题是在错误的方向上打字。我想将以下 github 问题添加为附件,因为除了下面的@matt 答案之外,它还为我提供了有用的信息:

https://github.com/golang/mock/issues/316#issuecomment-512043925

原帖

我是依赖注入的新手,想在使用couchbase go sdk的模块上对其进行测试。为此,我需要接口来重现ClusterBucket结构。

在 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 都会返回以下错误:

短绒错误 1

我还尝试将我的数据库接口中的 Bucket 方法签名替换为:

// Database mocks the gocb.Cluster interface.
type Database interface {
    Bucket(bucketName string) Bucket
}

这再次给了我以下 lint 错误:

短绒错误 2

如何实现一个接口来模拟这两种方法?

4

1 回答 1

2

我认为您缺少的关键概念是模拟对象必须与您所模拟的接口要求相匹配。这包括方法的参数和返回值。

type Database interface {
    // Bucket(bucketName string) *Bucket   // Wrong
    Bucket(bucketName string) *gocb.Bucket // Correct
}

您仍然可以使用Database.Bucketas a的返回值,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)
}
于 2021-03-05T20:52:15.570 回答