mongodb - Mocking official MongoDb driver
问题描述
I need to define these interfaces to mock official mongo driver
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
}
In mongo driver package there are two structs mongo.Collection and mongo.Database with these methods
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
}
The struct *mongo.Collection implement MgCollection correctly, so this code compiles without error
var col mgdriver.MgCollection
col = &mongo.Collection{}
col.FindOne(ctx, nil, nil)
But The struct *mongo.Database not implement MgDatabase, so I when I write something like this:
var db mgdriver.MgDatabase
db = &mongo.Database{}
db.Collection("Test", nil)
Compiler show this error:
cannot use &mongo.Database literal (type *mongo.Database) as type mgdriver.MgDatabase in assignment: *mongo.Database does not implement mgdriver.MgDatabase (wrong type for Collection method) have Collection(string, ...*options.CollectionOptions) *mongo.Collection want Collection(string, ...*options.CollectionOptions) mgdriver.MgCollection
Both mongo.Collection and mongo.Database are in the official package and I cannot change any code in that package. so how can I change my interfaces to mock official mongo driver correctly?
解决方案
通常,您不会。你应该做的是定义一个数据访问接口,
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 Proverb
一点点复制比一点点依赖要好。
(但请记住给予信用,并保留版权说明。)
因此,使用上述方法,您可以非常快速地针对模拟进行单元测试,并为您的测试量身定制稳定且可预测的答案,并且仅在绝对必须的情况下针对 MongoDB 进行相对昂贵且速度较慢的测试。
额外的好处:更换您的实际持久性技术相对容易。
推荐阅读
- python - 我无法在我的 anaconda 环境中安装 Jupyter 和 Matplotlib
- wpf - Windows 7 上生成的 Button 控件模板中的错误
- javascript - 为什么 ionChange/ngModelChange 是从我不调用的 ion-checkbox 执行的?
- php - 在两个 php 文件之间更改字符串
- javascript - 提交
- tensorflow - 在 Tensorflow 图中交换两个变量的值的最有效方法是什么?
- sharepoint-list - 如何检查是否选择了选择字段选项
- c++ - 类和它们之间的友元函数
- typescript - Typescript中数组对象的对象
- azure - 如何使用来自 EventGrids BlobCreated 事件数据的 URL 获取 Blob 的路径?