...

Source file src/go.mongodb.org/mongo-driver/mongo/integration/mock_find_test.go

Documentation: go.mongodb.org/mongo-driver/mongo/integration

     1  // Copyright (C) MongoDB, Inc. 2021-present.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License"); you may
     4  // not use this file except in compliance with the License. You may obtain
     5  // a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
     6  
     7  package integration
     8  
     9  import (
    10  	"context"
    11  	"testing"
    12  
    13  	"go.mongodb.org/mongo-driver/bson"
    14  	"go.mongodb.org/mongo-driver/bson/bsoncodec"
    15  	"go.mongodb.org/mongo-driver/internal/assert"
    16  	"go.mongodb.org/mongo-driver/mongo"
    17  	"go.mongodb.org/mongo-driver/mongo/integration/mtest"
    18  	"go.mongodb.org/mongo-driver/mongo/options"
    19  )
    20  
    21  // finder is an object that implements FindOne and Find.
    22  type finder interface {
    23  	FindOne(ctx context.Context, filter interface{}, opts ...*options.FindOneOptions) *mongo.SingleResult
    24  	Find(context.Context, interface{}, ...*options.FindOptions) (*mongo.Cursor, error)
    25  }
    26  
    27  // mockFinder implements finder.
    28  type mockFinder struct {
    29  	docs     []interface{}
    30  	err      error
    31  	registry *bsoncodec.Registry
    32  }
    33  
    34  // FindOne mocks a findOne operation using NewSingleResultFromDocument.
    35  func (mf *mockFinder) FindOne(_ context.Context, _ interface{}, _ ...*options.FindOneOptions) *mongo.SingleResult {
    36  	return mongo.NewSingleResultFromDocument(mf.docs[0], mf.err, mf.registry)
    37  }
    38  
    39  // Find mocks a find operation using NewCursorFromDocuments.
    40  func (mf *mockFinder) Find(context.Context, interface{}, ...*options.FindOptions) (*mongo.Cursor, error) {
    41  	return mongo.NewCursorFromDocuments(mf.docs, mf.err, mf.registry)
    42  }
    43  
    44  // ShopItem is an item with an associated ID and price.
    45  type ShopItem struct {
    46  	ID    int     `bson:"id"`
    47  	Price float64 `bson:"price"`
    48  }
    49  
    50  // getItem is an example function using the interface finder to test the mocking of SingleResult.
    51  func getItem(f finder, id int) (*ShopItem, error) {
    52  	res := f.FindOne(context.Background(), bson.D{{"id", id}})
    53  	var item ShopItem
    54  	err := res.Decode(&item)
    55  	return &item, err
    56  }
    57  
    58  // getItems is an example function using the interface finder to test the mocking of Cursor.
    59  func getItems(f finder) ([]ShopItem, error) {
    60  	cur, err := f.Find(context.Background(), bson.D{})
    61  	if err != nil {
    62  		return nil, err
    63  	}
    64  
    65  	var items []ShopItem
    66  	err = cur.All(context.Background(), &items)
    67  	return items, err
    68  }
    69  
    70  func TestMockFind(t *testing.T) {
    71  	mt := mtest.New(t, mtest.NewOptions().CreateClient(false))
    72  
    73  	insertItems := []interface{}{
    74  		ShopItem{ID: 0, Price: 1.5},
    75  		ShopItem{ID: 1, Price: 5.7},
    76  		ShopItem{ID: 2, Price: 0.25},
    77  	}
    78  	insertItem := []interface{}{ShopItem{ID: 1, Price: 5.7}}
    79  
    80  	mt.Run("mongo.Collection can be passed as interface", func(mt *mtest.T) {
    81  		// Actually insert documents to collection.
    82  		_, err := mt.Coll.InsertMany(context.Background(), insertItems)
    83  		assert.Nil(mt, err, "InsertMany error: %v", err)
    84  
    85  		// Assert that FindOne behaves as expected.
    86  		shopItem, err := getItem(mt.Coll, 1)
    87  		assert.Nil(mt, err, "getItem error: %v", err)
    88  		assert.Equal(mt, 1, shopItem.ID)
    89  		assert.Equal(mt, 5.7, shopItem.Price)
    90  
    91  		// Assert that Find behaves as expected.
    92  		shopItems, err := getItems(mt.Coll)
    93  		assert.Nil(mt, err, "getItems error: %v", err)
    94  		for i, shopItem := range shopItems {
    95  			expectedItem := insertItems[i].(ShopItem)
    96  			assert.Equal(mt, expectedItem.ID, shopItem.ID)
    97  			assert.Equal(mt, expectedItem.Price, shopItem.Price)
    98  		}
    99  	})
   100  
   101  	mt.Run("FindOne can be mocked", func(mt *mtest.T) {
   102  		// Mock a FindOne result with mockFinder.
   103  		mf := &mockFinder{docs: insertItem, err: nil, registry: nil}
   104  
   105  		// Assert that FindOne behaves as expected.
   106  		shopItem, err := getItem(mf, 1)
   107  		assert.Nil(mt, err, "getItem error: %v", err)
   108  		assert.Equal(mt, 1, shopItem.ID)
   109  		assert.Equal(mt, 5.7, shopItem.Price)
   110  	})
   111  
   112  	mt.Run("Find can be mocked", func(mt *mtest.T) {
   113  		// Mock a Find result with mockFinder.
   114  		mf := &mockFinder{docs: insertItems, err: nil, registry: nil}
   115  
   116  		// Assert that Find behaves as expected.
   117  		shopItems, err := getItems(mf)
   118  		assert.Nil(mt, err, "getItems error: %v", err)
   119  		for i, shopItem := range shopItems {
   120  			expectedItem := insertItems[i].(ShopItem)
   121  			assert.Equal(mt, expectedItem.ID, shopItem.ID)
   122  			assert.Equal(mt, expectedItem.Price, shopItem.Price)
   123  		}
   124  	})
   125  }
   126  

View as plain text