Vah*_*ari 4 unit-testing mocking go mongodb
我需要定义这些接口来模拟官方 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
}
Run Code Online (Sandbox Code Playgroud)
在 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
}
Run Code Online (Sandbox Code Playgroud)
struct *mongo.Collection正确实现了MgCollection,所以这段代码编译没有错误
var col mgdriver.MgCollection
col = &mongo.Collection{}
col.FindOne(ctx, nil, nil)
Run Code Online (Sandbox Code Playgroud)
但是 struct *mongo.Database没有实现MgDatabase,所以当我写这样的东西时:
var db mgdriver.MgDatabase
db = &mongo.Database{}
db.Collection("Test", nil)
Run Code Online (Sandbox Code Playgroud)
编译器显示此错误:
不能使用 &mongo.Database 文字(类型 *mongo.Database)作为赋值中的类型 mgdriver.MgDatabase:*mongo.Database 没有实现 mgdriver.MgDatabase(Collection 方法的类型错误)有 Collection(string, ...*options.CollectionOptions ) *mongo.Collection 想要 Collection(string, ...*options.CollectionOptions) mgdriver.MgCollection
无论mongo.Collection和mongo.Database在官方包,我不能在包更改任何代码。那么如何更改我的接口以正确模拟官方 mongo 驱动程序?
通常,您不会。你应该做的是定义一个数据访问接口,
type CRUD interface {
Create(yourModel) error
Read(page, size, skip) []yourModel
Update(yourModel) error
Delete(yourModel) error
}
Run Code Online (Sandbox Code Playgroud)
并实施它。
然后模拟界面,例如使用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
Run Code Online (Sandbox Code Playgroud)
由于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)
}
Run Code Online (Sandbox Code Playgroud)
仍然是你如何测试 CRUD 接口的实现的问题。我曾经使用过最初由 Gustavo Niemeyer 开发并由 globalsign 接管的 mgo 驱动程序。这带来了一个名为dbtest的漂亮小包。它实际上是一个围绕 MongoDB 实例的非常薄的包装器,可以按需启动和停止一个实例,并能够在测试之间重置数据。要么只是导入dbtest,要么引用 Go Proverb
一点点复制比一点点依赖要好。
(不过,请记住给予信用,并保留版权说明。)
因此,使用上述方法,您可以非常快速地针对模拟进行单元测试,并为您的测试量身定制稳定且可预测的答案,并且仅在绝对必要的情况下才对 MongoDB 进行相对昂贵和缓慢的测试。
额外的好处:更换您的实际持久性技术相对容易。