Ожидание инициализации моего класса (или как ждать завершения Future)?
Фьючерсы на Dart - проклятие моего существования.
У меня есть класс, который вызывает асинхронную (Future) функцию для запуска экземпляра базы данных следующим образом:
class DataManager {
bool DbIsReady = false;
Db _db;
DataManager() {
init_mongo_db();
}
void init_mongo_db() {
print("Initializing MongoDB");
_db = new Db("mongodb://127.0.0.1/test");
_db.open().then((_) {
DbIsReady = true;
});
}
Future<List> attemptLogin(String username, String password) {
users = _db.collection("users");
return // ... rest of code cut out for clarity
}
}
Это работает нормально на стороне сервера, потому что при первом запуске сервера база данных инициализируется. К тому времени, когда пользователь действительно пытается войти, база данных уже инициализирована, и все в порядке. Однако это с треском проваливается, когда я пытаюсь создать интеграционный тест для этого. Когда я создаю класс, база данных еще не инициализирована, поэтому выполнение процедуры AttemptLogin завершается неудачно.
DataManager db = new DataManager();
// This fails miserably, because db hasn't initialized yet.
db.AttemptLogin("test", "test");
Хуже того, в коде используется среда Dart DI, поэтому я не имею прямого контроля над инициализацией класса DataManager. Это фактическая настройка класса:
setUp(() {
app.addModule(new Module()
..bind(DataManager)
app.setUp();
});
И затем это вызов для проверки функциональности входа в систему, который в конечном итоге вызывает функцию tryLogin, которая завершается ошибкой:
var req = new MockRequest("/user/login", contentType: 'JSON', method:'POST',
body:JSON.encode(
{"username" : 'test',
"password" : 'test' }));
Как справиться с асинхронной природой инициализации базы данных и все еще проводить фиктивное тестирование? В частности, есть ли способ принудительно попытаться предпринять FutureLogin() Future для завершения инициализации класса DataManager?
Спасибо за вашу помощь, Грег
2 ответа
Как насчет использования решения @lrn s как
setUp(() {
return DataManager.createNew().then((dm) {
app.addModule(new Module()
..bind(DataManager, toValue: dm);
app.setUp();
}
});
Таким образом, вы уже проходите инициализированный DataManager
экземпляр в DI. Если вы запросите это позже, вы всегда можете быть уверены, что оно уже инициализировано.
Если ваш класс имеет асинхронную настройку, вы не можете использовать обычный конструктор. В этом случае я бы просто использовал фабричный метод, возвращающий будущее:
class DataManager {
final Db _db;
DataManager._(this._db);
static Future<DataManager> createNew() {
var db = new Db("mongodb://127.0.0.1/test");
return db.open().then((_) => new DataManager._(db));
}
...
};
Я не знаю, как вы подключаете это к своей структуре внедрения зависимостей, но я думаю, что это может сделать что-то со статическими методами.