Методы поиска и добавления BoltDB и советы по модульному тестированию

Я пишу пакет Go, который обрабатывает взаимодействие с BoltDB как часть более крупного проекта. У меня есть 2 метода взаимодействия с БД.

func Lookup(path string) (string, bool) {}
func RegisterUrl(path, url string) error {}

Lookup делает запрос к базе данных для получения соответствующего URL-адреса, тогда как RegisterUrl записывает пару ключ-значение path: url в базу данных.

Я хотел бы попросить обзор моей реализации и несколько советов по реализации модульных тестов.

Модульное тестирование

Я включил скелет для модульных тестов, которые я хотел бы иметь для двух вышеупомянутых функций. Однако мне сложно понять, как лучше всего их реализовать.

  • Я бы не хотел тестировать методы, использующие базу данных / ведро «prod», вместо этого я бы предпочел поменять местами prod DB для тестирования DB в database_test.go файл.
  • Я подумал о том, чтобы сделать общедоступные переменные dbName и bucketName в database.go а затем измените их в файле _test для test db, но похоже, что я нарушу инкапсуляцию.
  • Я также рассматривал возможность передачи тестовой базы данных / ведра в функции в качестве функциональных опций, но похоже, что это усложнит код, и я не уверен, что это лучший подход.

Буду рад услышать ваш совет.

database.go

// Package database handles communication with BoltDB.
package database

import (
    "log"
    "time"

    "github.com/boltdb/bolt"
)

var dbOptions *bolt.Options = &bolt.Options{
    Timeout: 1 * time.Second,
}

const (
    dbName     = "urls.db"
    bucketName = "UrlFromPath"
)

func init() {
    // Make sure that the database exists.
    db, err := bolt.Open(dbName, 0600, dbOptions)
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()
    // Make sure that UrlFromPath bucket exists.
    err = db.Update(func(tx *bolt.Tx) error {
        _, err := tx.CreateBucketIfNotExists([]byte(bucketName))
        if err != nil {
            return err
        }
        return nil
    })
    if err != nil {
        log.Fatal(err)
    }
}

// Lookup checks if `path` key exists in database and returns related `url` value if found. If not
// found second return value `ok` is set to false.
func Lookup(path string) (url string, ok bool) { // TODO: return
    // Open connection to DB.
    db, err := bolt.Open(dbName, 0600, dbOptions)
    if err != nil {
        log.Fatalf("Cannot connect to DB: %s", err)
        return "", false
    }
    defer db.Close()

    // Retreive url from DB.
    var url_bytes []byte
    err = db.View(func(tx *bolt.Tx) error {
        b := tx.Bucket([]byte(bucketName))
        url_bytes = b.Get([]byte(path))
        return nil
    })
    if err != nil {
        return "", false
    }
    if url_bytes != nil {
        return string(url_bytes), true
    } else {
        return "", false
    }

}

// RegisterUrl saves provided key:value (path:url) pair to database.
func RegisterUrl(path, url string) error {
    // Open connection to DB.
    db, err := bolt.Open(dbName, 0600, dbOptions)
    if err != nil {
        return err
    }
    defer db.Close()

    // Save path and url.
    err = db.Update(func(tx *bolt.Tx) error {
        b := tx.Bucket([]byte(bucketName))
        err := b.Put([]byte(path), []byte(url))
        return err
    })
    if err != nil {
        return err
    }

    log.Printf("Database: %s, %s registered.", path, url)
    return nil
}

database_test.go

package database

import "testing"

func setup() {
    // Init test db.
    // Init test bucket.
}

func cleanup() {
    // Remove test db.
}

func TestLookup(t *testing.T) {
    // T1. Path exists in db. Correct url is retrieved.

    // T2. Path doesn't exist in db. false is returned.

}

func TestRegisterUrl(t *testing.T) {
    // T1. Add path:url to db. Correct path:url pair has been added to db.
}
```

0

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *