mongodbgomocking

How to mock mongodb driver in golang


In my Golang project I need to mock mongodb to be able to write unit tests for my Repository functions. I mostly need to mock collection.Indexes.CreateMany or FindOneAndUpdateor Find or cursor.All or InsertOne etc. From what I see it is possible with mtest lib. But I couldn't manage to mock creating indexes. I need help with some examples of how to use mtest(or if there is a better option) for mocking mongo driver in golang(especially collection.FindOneAndUpdate and collection.Indexes.CreateMany)


Solution

  • Assuming you have a MyRepositoryFunction like this:

    package mypackage
    
    import (
        "context"
        "fmt"
    
        "go.mongodb.org/mongo-driver/bson"
        "go.mongodb.org/mongo-driver/mongo"
    )
    
    func MyRepositoryFunction(ctx context.Context, collection *mongo.Collection) error {
        models := []mongo.IndexModel{
            {Keys: bson.D{{"surname", 1}, {"firstName", 1}}},
            {Keys: bson.D{{"key", -1}}},
        }
        _, err := collection.Indexes().CreateMany(ctx, models)
        if err != nil {
            return fmt.Errorf("failed to created indexes: %w", err)
        }
    
        filter := bson.D{{"_id", "custom123"}}
        update := bson.D{{"$set", bson.D{
            {"key", 42},
        }}}
        result := collection.FindOneAndUpdate(ctx, filter, update)
        if result.Err() != nil {
            return fmt.Errorf("failed to created indexes: %w", result.Err())
        }
    
        return nil
    }
    

    you could use mtest like:

    package mypackage
    
    import (
        "context"
        "testing"
    
        "github.com/stretchr/testify/assert"
        "go.mongodb.org/mongo-driver/bson"
        "go.mongodb.org/mongo-driver/mongo/integration/mtest"
    )
    
    func TestMyRepositoryFunction(t *testing.T) {
        ctx := context.Background()
        mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
    
        mt.Run("MyRepositoryFunction", func(mt *mtest.T) {
            mt.AddMockResponses(
                mtest.CreateSuccessResponse(),
                mtest.CreateSuccessResponse(bson.E{
                    "value", bson.M{"_id": "custom123", "key": 24},
                }),
            )
    
            err := MyRepositoryFunction(ctx, mt.Coll)
    
            assert.NoError(t, err, "Should have successfully run")
        })
    }
    

    You have to know the order in which the functions are called and provide enough results in wire format to make the client happy. Also, you don't really mock the driver - this way you'll mock the server. It can be a little difficult, since you have to understand the protocol.