Модульное тестирование Go-функций, имеющих ORM-взаимодействия - PullRequest
0 голосов
/ 12 февраля 2019

Я написал функцию:

func AllItems(w http.ResponseWriter, r *http.Request) {
    db, err := gorm.Open("sqlite3", "test.db")
    if err != nil {
        panic("failed to connect database")
    }
    defer db.Close()

    var items [] Item
    db.Find(&items)
    fmt.Println("{}", items)

    json.NewEncoder(w).Encode(items)
}

Я хочу провести модульное тестирование на этом.В идеале, модульное тестирование означает, что каждая строка функции должна быть протестирована.Я не уверен, как я должен проверить, если соединение с базой данных открыто, а затем, если он отображает все содержимое базы данных.Как мне проверить этот код?

Эта функция является конечной точкой GET простого приложения CRUD.Код здесь .

1 Ответ

0 голосов
/ 12 февраля 2019

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

Например:

type myDatabaseInterface interface {
    Find(interface{}) // this signature should match the real db.Find()
}

func AllItems(w http.ResponseWriter, r *http.Request) {
    db, err := gorm.Open("sqlite3", "test.db")
    if err != nil {
        panic("failed to connect database")
    }
    defer db.Close()
    items := findItems(db)
    json.NewEncoder(w).Encode(items)
}

func find(db myDatabaseInterface) ([]Item) {
    var items []Item
    db.Find(&items)
    return items
}

Затем вы можете создавать макеты для ваших зависимостей и использовать их в своих тестах:

type mock struct {}

// mock should implement myDatabaseInterface to be able to pass it to the function
func (m *mock) Find(interface{}) {
    // implement the mock to satisfy your test
}

func Test_find(t *testing.T) {
    m := mock{}
    res := find(m)
    // do testing
}

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

func makeAllItemsHandler(db myDatabaseInterface) func(http.ResponseWriter, *http.Request) {
    return func(http.ResponseWriter, *http.Request) {
        items := findItems(db)
        json.NewEncoder(w).Encode(items)
    }
}

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

...