使用 Go Mongo-Driver 和 mtest 从 UpdateOne 模拟 UpdateResult

Fra*_*iak 4 mocking go mongodb mongo-go mongo-go-driver

我正在尝试使用该mtest包(https://pkg.go.dev/go.mongodb.org/mongo-driver/mongo/integration/mtest)对我的 MongoDB 调用执行一些模拟结果测试,但我可以似乎不知道如何正确模拟调用集合*mongo.UpdateResult时返回的值。UpdateOne(...)

这是演示该问题的片段:

package test

import (
    "context"
    "errors"
    "testing"

    "github.com/stretchr/testify/assert"
    "go.mongodb.org/mongo-driver/bson"
    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/integration/mtest"
)

func UpdateOneCall(mongoClient *mongo.Client) error {
    filter := bson.D{{Key: "SomeIDField", Value: "SomeID"}}
    update := bson.D{{Key: "$set", Value: bson.D{{Key: "ANewField", Value: true}}}}
    collection := mongoClient.Database("SomeDatabase").Collection("SomeCollection")
    updateResult, err := collection.UpdateOne(context.Background(), filter, update)
    if err != nil {
        return err
    }
    if updateResult.ModifiedCount != 1 {
        return errors.New("no field was updated")
    }
    return nil
}

func TestUpdateOneCall(t *testing.T) {
    mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
    defer mt.Close()

    mt.Run("Successful Update", func(mt *mtest.T) {

        mt.AddMockResponses(mtest.CreateSuccessResponse(
            bson.E{Key: "NModified", Value: 1},
            bson.E{Key: "N", Value: 1},
        ))

        err := UpdateOneCall(mt.Client)

        assert.Nil(t, err, "Should have successfully triggered update")
    })
}
Run Code Online (Sandbox Code Playgroud)

通话collection.UpdateOne(context.Background(), filter, update)效果非常好。没有返回任何错误。不幸的是,该updateResult.ModifiedCount值始终为 0。

我尝试了mtest.CreateSuccessResponse(...)and的多种组合bson.D,使用诸如NModifiedand之类的名称N(如代码片段中所示)以及ModifiedCountand MatchedCount。似乎没有什么能解决问题。

无论如何,有没有办法模拟这个调用,使其实际上返回一个值ModifiedCount

Fra*_*iak 6

@Vishwas Mallikarjuna 得到了正确的答案,所以我将他们的帖子保留为已接受的帖子,因为他们绝对应得的。然而,鉴于他们的发现,我只想扩展一点。

问题归结为区分大小写。现在我知道了,我能够嘲笑MatchedCountModifiedCountUpsertedCountUpsertedID

这段代码展示了如何影响所有这些值:

package test

import (
    "context"
    "testing"

    "github.com/stretchr/testify/assert"
    "go.mongodb.org/mongo-driver/bson"
    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/integration/mtest"
    "go.mongodb.org/mongo-driver/x/mongo/driver/operation"
)

const (
    mockMatchedCount            int64  = 5
    oneLessThanMockedMatchCount int64  = 4
    mockModifiedCount           int64  = 22
    mockUpsertedCount           int64  = 13
    mockUpsertedID              string = "CouldBeAnythingIThink"
)

func UpdateOneCall(mongoClient *mongo.Client) (*mongo.UpdateResult, error) {
    filter := bson.D{{Key: "SomeIDField", Value: "SomeID"}}
    update := bson.D{{Key: "$set", Value: bson.D{{Key: "ANewField", Value: true}}}}
    collection := mongoClient.Database("SomeDatabase").Collection("SomeCollection")
    return collection.UpdateOne(context.Background(), filter, update)
}

func TestUpdateOneCall(t *testing.T) {
    mt := mtest.New(t, mtest.NewOptions().ClientType(mtest.Mock))
    defer mt.Close()

    mt.Run("Successful Update", func(mt *mtest.T) {

        upsertedVals := make([]operation.Upsert, mockUpsertedCount)
        upsertedVals[0] = operation.Upsert{ID: mockUpsertedID}
        mt.AddMockResponses(mtest.CreateSuccessResponse(
            bson.E{Key: "n", Value: mockMatchedCount},
            bson.E{Key: "nModified", Value: mockModifiedCount},
            bson.E{Key: "upserted", Value: upsertedVals},
        ))

        result, err := UpdateOneCall(mt.Client)

        assert.Nil(t, err, "Should have successfully triggered update")
        assert.Equal(t, result.MatchedCount, oneLessThanMockedMatchCount)
        assert.Equal(t, result.ModifiedCount, mockModifiedCount)
        assert.Equal(t, result.UpsertedCount, mockUpsertedCount)
        assert.Equal(t, result.UpsertedID, mockUpsertedID)
    })
}
Run Code Online (Sandbox Code Playgroud)

另外,如果您想知道为什么实际result.MatchedCountoneLessThanMockedMatchCount,这取决于Upserted值的工作原理。如果您仔细检查逻辑,go.mongodb.org/mongo-driver@v1.10.2/mongo/collection.go您将在文件中找到解释它的这段代码:

opRes := op.Result()
res := &UpdateResult{
    MatchedCount:  opRes.N,
    ModifiedCount: opRes.NModified,
    UpsertedCount: int64(len(opRes.Upserted)),
}
if len(opRes.Upserted) > 0 {
    res.UpsertedID = opRes.Upserted[0].ID
    res.MatchedCount--
}

return res, err
Run Code Online (Sandbox Code Playgroud)