我正在尝试为 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 才能使我的程序正常工作。
也许我误解了单元测试的工作原理。任何帮助