BoltDB Lookup and Add methods and advice on unit testing I am writing a Go package that handles communication with BoltDB as a part of some larger project. I have 2 methods for interacting with DB.
func Lookup(path string) (string, bool) {}
func RegisterUrl(path, url string) error {}

Lookup makes a request to database to retrieve corresponding url, whereas RegisterUrl writes path:url key-value pair to DB.
I would like to ask for a review of my implementation and some advice on how to implement unit tests.
Unit Testing
I've included the skeleton for unit tests that I would like to have for above 2 functions. However I have trouble figuring what is the best way to implement them.

I wouldn't like to test methods using the &quot;prod&quot; database/bucket, rather then that I would prefer to swap prod DB to test DB in the database_test.go file.
I thought about making dbName and bucketName public variables in database.go and then change them in _test file for test db, but this seems like I would be breaking the encapsulation.
I also considered passing test database/bucket to functions as functional options, but this seems like it will make code more complicated and I am not sure if this is the best approach.

I would be happy to hear your advice.
database.go
// Package database handles communication with BoltDB.
package database

import (
    &quot;log&quot;
    &quot;time&quot;

    &quot;github.com/boltdb/bolt&quot;
)

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

const (
    dbName     = &quot;urls.db&quot;
    bucketName = &quot;UrlFromPath&quot;
)

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(&quot;Cannot connect to DB: %s&quot;, err)
        return &quot;&quot;, 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 &quot;&quot;, false
    }
    if url_bytes != nil {
        return string(url_bytes), true
    } else {
        return &quot;&quot;, 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(&quot;Database: %s, %s registered.&quot;, path, url)
    return nil
}


database_test.go
package database

import &quot;testing&quot;

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.
}
```
I think the code could benefit a struct for the database instead of global state.
You can use a New method instead of init() where you pass in the params, which would differet from test and production.
I also demonstrated that you can keep the connection open and reuse it within the struct. If you prefer a lazy approach, you can omit this and create a the connection in each call if you want.
type Database struct {
   bucketName string 
   boltDB *bolt.DB
}

func New(dbName, bucketName string, opts *bolt.Options) (db *Database, error) {
   db, err := bolt.Open(dbName, 0600, opts)
   return &amp;Database{
      boltDb: db,
      bucketName: bucketName
   }, nil
}

func(db *Database) Lookup(path string) (url string, ok bool) { // lookup logic }
func(db *Database) RegisterUrl(path, url string) error { //register logic}
```