NOTICE

This repo is restored. I’ve deleted it from github, which broke InVisionApp/go-health: InVisionApp/go-health#79

I’m sorry for this!

Wrapper with mocks for MongoDB and BoltDB

Package shows how to mock MongoDB or BoltDB using a single Go interface. It’s not cover all db methods from the globalsign/mgo driver’s package. Feel free to extend the package according to your needs.

Package inspired by this article – Mocking Mongo in Go

Table of contents

How to install

go get github.com/zaffka/mongodb-boltdb-mock

Package contents

  • Wrapper itself (db/db.go) with:

    • db.Handler – main interface for opening, closing and controling connection to DB
    • db.Querier – interface for selecting data from DB
    • db.Refiner – interface for refining query object obtained by the Find() method
  • Realization for the MongoDB (db/mgo.go)

  • Realization for the BoltDB (db/bolt.go)

  • A set of mocks (db/mock.go)

  • Unit tests (db/db_test.go)

Interface methods being in use by realization

Interface/Function MongoDB Mocks BoltDB
db.New() + + +
db.Handler      
Connect + + +
Copy + +
CopyWithSettings + +
Close + + +
ExecOn + + +
db.Querier      
Insert + + +
Remove + + +
RemoveAll + +
Update + +
UpdateAll + +
Upsert + +
Find + + +
db.Refiner      
One + + +
All + +
Distinct + +
Count + +

MongoDB examples

…up the db

mongo := db.New(&db.Mongo{})
err := mongo.Connect("mongo://localhost:/27017")
defer mongo.Close()

…inserting data

func main() {
mongo := db.New(&db.Mongo{})
err := mongo.Connect("mongo://localhost:/27017")
defer mongo.Close()

os := new(OurStuct)
os.Save(mongo)
}

type OurStruct struct {}
func (o *OurStruct) Save(db db.Handler, databaseName, collectionName string) error {
    sess := db.Copy() //Pay attention globalsign's driver whant us to use
	defer sess.Close() //copied or clonned session of the *mgo.Session object

	err := sess.ExecOn(databaseName, collectionName).Insert(o)
	if err != nil {
		return err
	}

	return nil
}

…reading

func main() {
mongo := db.New(&db.Mongo{})
err := mongo.Connect("mongo://localhost:/27017")
defer mongo.Close()

os := new(OurStuct)
os.Save(mongo)
}

type OurStruct struct {
    ID bson.ObjectID `bson:"_id"`
}
func (o *OurStruct) Read(db db.Handler, databaseName, collectionName string) error {
	sess := db.Copy()
	defer sess.Close()

	err := sess.ExecOn(databaseName, collectionName).Find(o.ID).One(o)
	if err != nil {
		return err
	}

	return nil
}

…updating

func main() {
mongo := db.New(&db.Mongo{})
err := mongo.Connect("mongo://localhost:/27017")
defer mongo.Close()

os := new(OurStuct)
os.Save(mongo)
}

type OurStruct struct {
    ID bson.ObjectID `bson:"_id"`
}
func (o *OurStruct) Update(db db.Handler, databaseName, collectionName, update string) error {
	sess := db.Copy()
	defer sess.Close()

	_, err := sess.ExecOn(databaseName, collectionName).Upsert(bson.M{"_id": o.ID}, bson.M{"$set": bson.M{"somefield": update}})
	if err != nil {
		return err
	}

	return nil
}

and so on…

BoltDB examples

Features:

  • Database opens at the system’s temp directory (/tmp @ linux)
  • Working directory with db file will look like /tmp/[basename][random numbers]/[basename]
  • bolt.Close() removes the working directory and a db file
  • Use boltbrowser to work with bolt’s files
  • Any structs and data types can be used as keys and values to store in BoltDB (Gob marshaling\unmarshaling inside)
  • BoltDB uses buckets as Mongo’s collections analogues

…up the db

bolt := db.New(&db.Bolt{})
err := bolt.Connect("bolt", "bucketOne", "bucketTwo")
defer bolt.Close()

Where "bolt" – it’s a [basename] and others are variadic set of buckets names. If the list scipped bucket with the default name being in use.

…inserting data

bolt := db.New(&db.Bolt{})
err := bolt.Connect("bolt", "bucketOne", "bucketTwo")
defer bolt.Close()

err = bolt.ExecOn("bucketOne").Insert("key", &db.Mock{Msg: "test"})
if err != nil {
	log.Error(err)
}

…reading

...
var res db.Mock
err := bolt.ExecOn("bucketOne").Find("key").One(&res)
...

…deleting

...
err := bolt.ExecOn("bucketOne").Remove("key")
...

Mocking

Just replace &db.Mongo{} (or &db.Bolt{}) with &db.Mock{} and cover your functions by unit tests with ease. No real database needed.

func main() {
mongo := db.New(&db.Mongo{})
mongo.ExecOn(...).Find(...)...
...

replace with

func main() {
mock := db.New(&db.Mock{})
mongo.ExecOn(...).Find(...)...
...

GitHub

View Github