2

我正在尝试为 mongo go 驱动程序编写接口来为我的 post_repo.go 编写单元测试,但出现此错误:

cannot use redditclone (type *mongo.Database) as type newPosts.DatabaseHelper in argument to newPosts.NewPostsDatabase:
    *mongo.Database does not implement newPosts.DatabaseHelper (wrong type for Client method)
        have Client() *mongo.Client
        want Client() newPosts.ClientHelper

我的接口文件,取自这篇文章https://medium.com/better-programming/unit-testing-code-using-the-mongo-go-driver-in-golang-7166d1aa72c0

package newPosts

import (
    "context"
    "rc/pkg/config"

    // "localhost/medium-mongo-go-driver/config"

    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/options"
)

type DatabaseHelper interface {
    Collection(name string) CollectionHelper
    Client() ClientHelper
}

type CollectionHelper interface {
    FindOne(context.Context, interface{}) SingleResultHelper
    InsertOne(context.Context, interface{}) (interface{}, error)
    DeleteOne(ctx context.Context, filter interface{}) (int64, error)
}

type SingleResultHelper interface {
    Decode(v interface{}) error
}

type ClientHelper interface {
    Database(string) DatabaseHelper
    Connect() error
    StartSession() (mongo.Session, error)
}

type mongoClient struct {
    cl *mongo.Client
}
type mongoDatabase struct {
    db *mongo.Database
}
type mongoCollection struct {
    coll *mongo.Collection
}

type mongoSingleResult struct {
    sr *mongo.SingleResult
}

type mongoSession struct {
    mongo.Session
}

func NewClient(cnf *config.Config) (ClientHelper, error) {
    c, err := mongo.NewClient(options.Client().SetAuth(
        options.Credential{
            Username:   cnf.Username,
            Password:   cnf.Password,
            AuthSource: cnf.DatabaseName,
        }).ApplyURI(cnf.URL))

    return &mongoClient{cl: c}, err

}

func NewDatabase(cnf *config.Config, client ClientHelper) DatabaseHelper {
    return client.Database(cnf.DatabaseName)
}

func (mc *mongoClient) Database(dbName string) DatabaseHelper {
    db := mc.cl.Database(dbName)
    return &mongoDatabase{db: db}
}

func (mc *mongoClient) StartSession() (mongo.Session, error) {
    session, err := mc.cl.StartSession()
    return &mongoSession{session}, err
}

func (mc *mongoClient) Connect() error {
    // mongo client does not use context on connect method. There is a ticket
    // with a request to deprecate this functionality and another one with
    // explanation why it could be useful in synchronous requests.
    // https://jira.mongodb.org/browse/GODRIVER-1031
    // https://jira.mongodb.org/browse/GODRIVER-979
    return mc.cl.Connect(nil)
}

func (md *mongoDatabase) Collection(colName string) CollectionHelper {
    collection := md.db.Collection(colName)
    return &mongoCollection{coll: collection}
}

func (md *mongoDatabase) Client() ClientHelper {
    client := md.db.Client()
    return &mongoClient{cl: client}
}

func (mc *mongoCollection) FindOne(ctx context.Context, filter interface{}) SingleResultHelper {
    singleResult := mc.coll.FindOne(ctx, filter)
    return &mongoSingleResult{sr: singleResult}
}

func (mc *mongoCollection) InsertOne(ctx context.Context, document interface{}) (interface{}, error) {
    id, err := mc.coll.InsertOne(ctx, document)
    return id.InsertedID, err
}

func (mc *mongoCollection) DeleteOne(ctx context.Context, filter interface{}) (int64, error) {
    count, err := mc.coll.DeleteOne(ctx, filter)
    return count.DeletedCount, err
}

func (sr *mongoSingleResult) Decode(v interface{}) error {
    return sr.sr.Decode(v)
}

我的 post_repo.go 文件:

package newPosts

import (
    "context"
    // "localhost/medium-mongo-go-driver/models"
)

const collectionName = "posts"

// PostsDatabase user database representation to find, update, delete users
type PostsDatabase interface {
    FindOne(context.Context, interface{}) (*Post, error)
    Create(context.Context, *Post) error
    DeleteByUsername(context.Context, string) error
}

type postsDatabase struct {
    // db *mongo.Database
    db DatabaseHelper
}

// NewPostsDatabase creates new user database instance
func NewPostsDatabase(db DatabaseHelper) PostsDatabase {
    return &postsDatabase{
        db: db,
    }
}

func (u *postsDatabase) FindOne(ctx context.Context, filter interface{}) (*Post, error) {
    user := &Post{}
    err := u.db.Collection(collectionName).FindOne(ctx, filter).Decode(user)
    if err != nil {
        return nil, err
    }
    return user, nil
}

func (u *postsDatabase) Create(ctx context.Context, usr *Post) error {
    _, err := u.db.Collection(collectionName).InsertOne(ctx, usr)
    return err
}

func (u *postsDatabase) DeleteByUsername(ctx context.Context, username string) error {
    // In this case it is possible to use bson.M{"username":username} but I tend
    // to avoid another dependency in this layer and for demonstration purposes
    // used omitempty in the model
    author := &Author{Username: username}
    post := &Post{
        Author: author,
    }
    _, err := u.db.Collection(collectionName).DeleteOne(ctx, post)
    return err
}

我的 posts_repo_test.go 测试工作正常,但前提是我在函​​数 newPosts.NewPostsDatabase() 中通过 newPosts.DatabaseHelper。我想我需要通过 *mongo.Database 才能使我的程序正常工作。

也许我误解了单元测试的工作原理。任何帮助

4

0 回答 0