Отложенная очистка теста ведет себя по-разному в зависимости от того, где я ее вызываю - PullRequest
0 голосов
/ 26 мая 2018

У меня есть тест, который имеет следующую структуру:

var testInstance aetest.Instance // initialized by a TestMain

TestThing(t *testing.T) {
    defer cleanupGoogleDatastore(t, testInstance)

    // insert basic test fixtures

    // insert some new records here

    // test assertions, etc.
}

Метод cleanupGoogleDatastore просто выполняет запрос к хранилищу данных для всех сущностей определенного вида сущностей, а затем удаляет их одну за другой,Источник здесь:

func cleanupGoogleDatastore(t *testing.T, testInstance aetest.Instance) {
    q := datastore.NewQuery("Order")
    ctx := GetContext(t, testInstance)
    scanner := q.Run(ctx)
    for {
        var o model.Order
        key, err := scanner.Next(&o)
        if err == datastore.Done {
            return
        }
        if err != nil {
            t.Fatal(err.Error())
        }
        err = datastore.Delete(ctx, key)
        if err != nil {
            t.Fatal(err.Error())
        }
    }
}

Проблема, с которой я столкнулся, заключается в том, что записи, вставленные после «основных тестовых приспособлений», не удаляются этим отложенным оператором очистки.

Если я изменю эту функцию теста, вместо этого она будет выглядеть следующим образом:

var testInstance aetest.Instance // initialized by a TestMain  

TestThing(t *testing.T) {
    defer cleanupGoogleDatastore(t, testInstance)

    // insert basic test fixtures

    // insert some new records here

    defer cleanupGoogleDatastore(t, testInstance)
    // note that I have to call it TWICE - just moving it here is not enough.

    // test assertions, etc.
}

, тогда вновь созданные записи также будут удалены в конце теста.Насколько я понимаю, функции deferred просто вызываются в конце исходной области действия функции, что подразумевает, что запрос не будет построен и запущен до конца теста, но это не такВот.Похоже, что запрос строится , когда оператор defer называется , а затем выполняется в конце теста.

Я пытался переместить cleanupGoogleDatastore в замыкание (например, defer func() { cleanupGoogleDatastore(t, testInstance }(), и это ничего не изменило.

Я подозреваю, что это как-то случай оцениваемых аргументов функциив тот момент, когда я вызываю defer, а не когда вызывается функция, но так как t и testInstance являются указателями, а не прямыми значениями, я не уверен, как это может происходить. Нет других доказательств того, что эти два значенияПосле распечатки полей обеих структур в разных логических точках оценки ничего нового не появляется.

Что здесь происходит?

1 Ответ

0 голосов
/ 27 мая 2018

Это оказалось преднамеренным свойством локальной заглушки хранилища данных App Engine, которая по умолчанию возвращает слабосогласованные запросы.Мне удалось решить эту проблему, изменив код для cleanupGoogleDatastore, чтобы он полагался на запрос предка, который успешно нашел, а затем удалил все объекты.Альтернативным подходом было бы установить aetest.Instance, чтобы он был строго согласованным, но я не хотел навязывать строго согласованное поведение во всех моих тестах - только в этом.

...