prototype26
prototype26

Reputation: 141

How to properly unit test mongoDB CRUD result

My application mostly consists of CRUDs to/from MongoDB using mongo-go-drive package. This function is one of gRPC server services and all it does is calling database method action.GetProducts(ctx) and it returns *mongo.cursor. Then the result is decoded. For each document, I put the document content into a singular product struct, then append it to products slices (the GetProductsResponse struct is made using gRPC proto repeated GetProductResponse type). After appending all product into GetProductsResponse, I return the response to gRPC client.

I am also new to testing in general, how should I break down the function and do the mocking (how to mock the cursor?) for unit testing? Is it even necessary in the first place to do unit test on the function even though all it does is appending the result, or should I just go straight for the integration test and skip the unit test since it involves database 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
}

Upvotes: 1

Views: 2158

Answers (1)

Alessandro Argentieri
Alessandro Argentieri

Reputation: 3215

If you interact with the DB is not unit testing anymore, because you're integrating with another external system.

Anyway, I use to define my "repository" layer function this way:

package repo

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

and then, when I have to test my "service" layer logic, I would mock the entire "repository" layer this way:

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

Upvotes: 1

Related Questions