如何正确地对 mongoDB CRUD 结果进行单元测试

How to properly unit test mongoDB CRUD result

我的应用程序主要由使用 mongo-go-drive 包的 CRUD to/from MongoDB 组成。此函数是 gRPC 服务器服务之一,它所做的只是调用数据库方法 action.GetProducts(ctx) 和 returns *mongo.cursor。然后结果被解码。对于每个文档,我将文档内容放入一个单一的产品结构中,然后将其附加到产品切片(GetProductsResponse 结构是使用 gRPC 原型 repeated GetProductResponse 类型制作的)。将所有产品附加到 GetProductsResponse 后,我 return 对 gRPC 客户端的响应。

我也是一般测试的新手,我应该如何分解功能并进行单元测试的模拟(如何模拟光标?)?是否有必要首先对函数进行单元测试,即使它所做的只是附加结果,还是我应该直接进行集成测试并跳过单元测试,因为它涉及数据库 I/O?

func (s *Server) GetProducts(ctx context.Context, in *pb.EmptyRequest) (*pb.GetProductsResponse, error) {
    cursor, err := action.GetProducts(ctx)
    if err != nil {
        return nil, err
    }

    products := pb.GetProductsResponse{}

    res := model.Product{}

    for cursor.Next(ctx) {
        // Convert document to above struct
        err := cursor.Decode(&res)
        if err != nil {
            return nil, fmt.Errorf("failed to decode document: %v", err)
        }

        product := &pb.GetProductResponse{ProductId: res.Product_id.Hex(), Name: res.Name, Price: res.Price, Qty: int32(res.Qty)}

        products.Products = append(products.Products, product)
    }

    return &products, nil
}

如果您与数据库交互,则不再是单元测试,因为您正在与另一个外部系统集成。

无论如何,我用这种方式定义我的“存储库”层函数:

package repo

var FetchUserById = func(id string) (*model.User, error){
    // here the real logic
    return user, err
}

然后,当我必须测试我的“服务”层逻辑时,我会这样模拟整个“存储库”层:

repo.FetchUserById = func(id string) (*model.User, err) {
   return myMockedUser, nil
}