Насмешливый ответ MongoDB в Go - PullRequest
0 голосов
/ 26 июня 2019

Я извлекаю документ из MongoDB и передаю его в функцию transform, например.

var doc map[string]interface{}
err := collection.FindOne(context.TODO(), filter).Decode(&doc) 
result := transform(doc)

Я хочу написать модульные тесты для transform, но я не уверен, как посмеяться над ответом из MongoDB. В идеале я хочу настроить что-то вроде этого:

func TestTransform(t *testing.T) {
    byt := []byte(`
    {"hello": "world",
     "message": "apple"}
 `)

    var doc map[string]interface{}

    >>> Some method here to Decode byt into doc like the code above <<<

    out := transform(doc)
    expected := ...
    if diff := deep.Equal(expected, out); diff != nil {
        t.Error(diff)
    }
}

Одним из способов было бы json.Unmarshal в doc, но иногда это дает разные результаты. Например, если документ в MongoDB содержит массив, то этот массив декодируется в doc как тип bson.A, а не тип []interface{}.

Ответы [ 2 ]

0 голосов
/ 10 июля 2019

Использование библиотеки обезьян для подключения любой функции из драйвера монго.

Например:

func insert(collection *mongo.Collection) (int, error) {
    ctx, _ := context.WithTimeout(context.Background(), 10*time.Second)

    u := User{
        Name: "kevin",
        Age:  20,
    }

    res, err := collection.InsertOne(ctx, u)
    if err != nil {
        log.Printf("error: %v", err)
        return 0, err
    }

    id := res.InsertedID.(int)
    return id, nil
}

func TestInsert(t *testing.T) {
    var c *mongo.Collection

    var guard *monkey.PatchGuard
    guard = monkey.PatchInstanceMethod(reflect.TypeOf(c), "InsertOne",
        func(c *mongo.Collection, ctx context.Context, document interface{}, opts ...*options.InsertOneOptions) (*mongo.InsertOneResult, error) {
            guard.Unpatch()
            defer guard.Restore()

            log.Printf("record: %+v, collection: %s, database: %s", document, c.Name(), c.Database().Name())
            res := &mongo.InsertOneResult{
                InsertedID: 100,
            }

            return res, nil
        })

    collection := client.Database("db").Collection("person")
    id, err := insert(collection)

    require.NoError(t, err)
    assert.Equal(t, id, 100)
}
0 голосов
/ 26 июня 2019

Лучшим решением для написания тестируемого кода может быть извлечение кода в DAO или Data-Repository. Вы должны определить интерфейс, который будет возвращать то, что вам нужно. Таким образом, вы можете просто использовать Mocked-версию для тестирования.

// repository.go
type ISomeRepository interface {
    Get(string) (*SomeModel, error)
}

type SomeRepository struct { ... }

func (r *SomeRepository) Get(id string) (*SomeModel, error) {
    // Handling a real repository access and returning your Object
}

Когда вам нужно его смоделировать, просто создайте Mock-Struct и реализуйте интерфейс:

// repository_test.go

type SomeMockRepository struct { ... }

func (r *SomeRepository) Get(id string) (*SomeModel, error) {
    return &SomeModel{...}, nil
}

func TestSomething() {
    // You can use your mock as ISomeRepository
    var repo *ISomeRepository
    repo = &SomeMockRepository{}
    someModel, err := repo.Get("123")
}

Лучше всего использовать с каким-либо внедрением зависимостей , поэтому этот репозиторий передается как ISomeRepository в функцию.

...