英文:
Mock UpdateResult From UpdateOne Using Go Mongo-Driver And mtest
问题
我正在尝试使用mtest
包(https://pkg.go.dev/go.mongodb.org/mongo-driver/mongo/integration/mtest)对我的MongoDB调用进行一些测试,并使用模拟结果,但是我似乎无法弄清楚如何正确模拟在集合上进行UpdateOne(...)
调用时返回的*mongo.UpdateResult
值。
这里是一个演示问题的代码片段:
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")
})
}
collection.UpdateOne(context.Background(), filter, update)
调用完全正常。没有返回错误。不幸的是,updateResult.ModifiedCount
的值始终为0。
我尝试了多种mtest.CreateSuccessResponse(...)
和bson.D
的组合,使用了NModified
和N
等名称(如代码片段中所示),以及ModifiedCount
和MatchedCount
。但是似乎没有什么效果。
有没有办法模拟这个调用,使其实际上返回ModifiedCount
的值?
英文:
I'm trying to use the mtest
package (https://pkg.go.dev/go.mongodb.org/mongo-driver/mongo/integration/mtest) to perform some testing with mock results on my MongoDB calls, but I can't seem to figure out how to properly mock the *mongo.UpdateResult
value that gets returned when you make an UpdateOne(...)
call on a collection.
Here is a snippet demonstrating the problem:
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")
})
}
The collection.UpdateOne(context.Background(), filter, update)
call works perfectly fine. There are no errors returned. Unfortunately, the updateResult.ModifiedCount
value is always 0.
I've tried multiple combinations of mtest.CreateSuccessResponse(...)
and bson.D
, utilizing names such as NModified
and N
(as can be seen in the snippet), as well as ModifiedCount
and MatchedCount
. Nothing seems to do the trick.
Is there anyway to mock this call such that it actually returns a value for the ModifiedCount
?
答案1
得分: 2
mt.AddMockResponses(bson.D{
{"ok", 1},
{"nModified", 1},
})
这对我来说有效,可以得到ModifiedCount:1。
英文:
mt.AddMockResponses(bson.D{
{"ok", 1},
{"nModified", 1},
})
This worked for me to get ModifiedCount : 1
答案2
得分: 1
@Vishwas Mallikarjuna给出了正确的答案,所以我将保留他们的帖子作为被接受的答案,因为他们绝对值得。然而,根据他们的发现,我只是想稍微扩展一下。
问题归结为大小写敏感性。现在我知道了这一点,我能够模拟MatchedCount
、ModifiedCount
、UpsertedCount
和UpsertedID
。
以下代码片段展示了如何影响所有这些值:
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)
})
}
另外,如果你想知道为什么实际的result.MatchedCount
是oneLessThanMockedMatchCount
,这与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
英文:
@Vishwas Mallikarjuna got the right answer, so I'm leaving their post as the accepted one because they absolutely deserve that. However, given their findings, I just wanted to expand a little bit.
The issue came down to case-sensitivity. Now that I know that, I was able to mock the MatchedCount
, ModifiedCount
, UpsertedCount
, and the UpsertedID
.
This chunk of code shows how you would go about influencing all of these values:
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)
})
}
Also, if you're wondering why the actual result.MatchedCount
is oneLessThanMockedMatchCount
, it comes down to how having an Upserted
value works. If you go through the logic, in the file go.mongodb.org/mongo-driver@v1.10.2/mongo/collection.go
you'll find this chunk of code that explains it:
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论