我需要定义这些接口来模拟正式的mongo驱动程序
type MgCollection interface {
FindOne(ctx context.Context, filter interface{}, opts ...*options.FindOneOptions) *mongo.SingleResult
// Other methods
}
type MgDatabase interface {
Collection(name string, opts ...*options.CollectionOptions) MgCollection
// Other methods
}
在mongo驱动程序包中,有两种使用这些方法的结构 mongo.Collection 和 mongo.Database
func (coll *Collection) FindOne(ctx context.Context, filter interface{}, opts ...*options.FindOneOptions) *SingleResult {
// Method code
}
func (db *Database) Collection(name string, opts ...*options.CollectionOptions) *Collection {
// Method code
}
结构 * mongo.Collection 正确实现了 MgCollection ,因此该代码可以正确编译
var col mgdriver.MgCollection
col = &mongo.Collection{}
col.FindOne(ctx, nil, nil)
但是结构 * mongo.Database 无法实现 MgDatabase ,所以我在编写类似这样的内容时:
var db mgdriver.MgDatabase
db = &mongo.Database{}
db.Collection("Test", nil)
编译器显示此错误:
不能使用&mongo.Database文字(类型* mongo.Database)作为类型 分配中的mgdriver.MgDatabase:* mongo.Database未实现 mgdriver.MgDatabase(错误的Collection方法类型)具有 Collection(字符串,... * options.CollectionOptions)* mongo.Collection 想要Collection(string,... * options.CollectionOptions) mgdriver.MgCollection
mongo.Collection 和 mongo.Database 都在官方程序包中,我无法更改该程序包中的任何代码。那么如何更改我的界面以正确模拟官方mongo驱动程序?
答案 0 :(得分:2)
通常,您不需要。您应该做的是定义一个数据访问接口
type CRUD interface {
Create(yourModel) error
Read(page, size, skip) []yourModel
Update(yourModel) error
Delete(yourModel) error
}
并实施它。
然后,您可以模拟界面,例如使用testify/mock:
type MockedCRUD struct {
mock.Mock
}
func(m *MockedCRUD)Create(y yourModel) error{
returned m.Called(y).Error(0)
}
// And so on and so forth
由于MockedCRUD
满足CRUD接口,因此您可以像使用MongoCRUD
实现那样使用它,而不会遇到任何麻烦:
func TestYourApplicationLogicCallingCreate( t *testing.T){
model := YourModel{Type: ”Baz”})
mocked := new(MockedCRUD)
mocked.On(”Create”,model).Return(ErrInvalidType)
app := YourApplication{CRUD:mocked}
err := app.yourApplicationLogicCallingCreate(model)
assert.Error(t,err)
assert.Equal(t,ErrInvalidType,err)
}
仍然是一个问题,您如何测试CRUD接口的实现。我曾经使用过最初由Gustavo Niemeyer开发并由globalsign接管的mgo驱动程序。那带来了一个叫做dbtest的漂亮小包装。实际上,它是围绕MongoDB实例的非常薄的包装器,可以按需启动和停止实例,并能够在两次测试之间重置数据。要么导入dbtest
,要么引用Go Pro谚语
一点点拷贝比一点点依赖要好。
(不过请记住要感谢您,并保留版权说明。)
因此,使用上述方法,您可以对模拟进行相当快速的单元测试,并为测试量身定制稳定且可预测的答案,并且仅在绝对必要时才对MongoDB进行相对昂贵且缓慢的测试。
增加的好处:换出您的实际持久性技术相对容易。