如何使用 mongo-go-driver 模拟聚合

问题描述 投票:0回答:1

我正在尝试模拟 mongoDB 函数

Aggregate
,但它不断返回
command failed
的一般错误。

如果有人感兴趣,有一个关于其他功能以及如何模拟它们的好博客Mock mongo-go-driver

功能正在测试中

func (b *BlogsRepo) CountTagsInBlogs(ctx context.Context) (map[string]int, error) {
    clog := log.GetLoggerFromContext(ctx)

    // Specify the pipeline to group and count tags
    pipeline := []bson.M{
        {
            "$unwind": "$tags",
        },
        {
            "$group": bson.M{
                "_id":   "$tags",
                "count": bson.M{"$sum": 1},
            },
        },
    }

    // Aggregate the data based on the pipeline
    cursor, err := b.collection.Aggregate(ctx, pipeline)
    if err != nil {
        clog.ErrorCtx(err, log.Ctx{
            "msg": "Error aggregating data",
            "err": err,
        })

        return nil, err
    }
    defer cursor.Close(ctx)

    // Create a map to store tag counts
    tagCounts := make(map[string]int)

    // Iterate through the results and populate the map
    for cursor.Next(ctx) {
        var result struct {
            Tag   string `bson:"_id"`
            Count int    `bson:"count"`
        }
        if err := cursor.Decode(&result); err != nil {
            clog.ErrorCtx(err, log.Ctx{
                "msg": "Error decoding result"},
            )

            return nil, err
        }
        tagCounts[result.Tag] = result.Count
    }

    return tagCounts, nil
}

测试

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

    testCases := []struct {
        name           string
        mockedResponse []bson.D
        expected       map[string]int
        err            error
    }{
        {
            name: "successful count tags response",
            mockedResponse: []bson.D{
                {{"_id", "java"}, {"count", 3}},
                {{"_id", "go"}, {"count", 7}},
                {{"_id", "kotlin"}, {"count", 3}},
            },
            expected: map[string]int{
                "java":   3,
                "go":     7,
                "kotlin": 3,
            },
            err: nil,
        },
    }

    for _, tc := range testCases {
        tc := tc
        mt.Run(tc.name, func(mt *mtest.T) {
            // Mock the aggregation response
            mt.AddMockResponses(tc.mockedResponse...)

            blogRepo := NewBlogRepository(mt.Client, mt.Coll)

            // Call the method being tested
            tagCounts, err := blogRepo.CountTagsInBlogs(ctx)

            // Check the returned values against the expected values
            assert.Equal(t, tc.expected, tagCounts, "Tag counts do not match expected values")
            assert.NoError(t, err)

        })
    }
}

错误:

        Error:          Received unexpected error:
                        command failed
        Test:           TestBlogsRepo_CountTagsInBlogs

还有第二个错误,但这只是因为错误被捕获,返回的地图是

nil
,与预期结果不符。

错误发生在这里

cursor, err := b.collection.Aggregate(ctx, pipeline)
if err != nil {
    clog.ErrorCtx(err, log.Ctx{
        "msg": "Error aggregating data",
        "err": err,
    })

    return nil, err
}
defer cursor.Close(ctx)

模拟看起来正确。任何建议将不胜感激。

mongodb go
1个回答
0
投票

要模拟

Collection.Aggregate()
调用的响应,您必须使用
mtest.CreateCursorResponse()
创建和使用光标响应。

所以这样做:

for i, tc := range testCases {
    tc := tc
    mt.Run(tc.name, func(mt *mtest.T) {
        // Mock the aggregation response
        mt.AddMockResponses(mtest.CreateCursorResponse(
            0,
            fmt.Sprintf("%s.%d", tc.name, i),
            mtest.FirstBatch,
            tc.mockedResponse...,
        ))
© www.soinside.com 2019 - 2024. All rights reserved.