Как я могу сбросить состояние Realm между тестами?
Мы использовали RLMClearRealmCache
очистить состояние Realm между тестами, которые тестируют миграции. Если кэш не очищен, следующий тест не выполнит миграцию, поскольку кэш все еще сообщает о обновлении схемы, даже если мы удалили и заменили файл фиксации области (который имеет старую схему).
RLMClearRealmCache
был недавно перемещен в файл Objective-C++, поэтому мы хотим прекратить его использование и избегать использования Objective-C++ в нашем проекте. Это все еще лучший / единственный способ сделать это?
Чтобы было ясно, мы не используем в памяти Realm для этих спецификаций. У нас есть default.realm
файл фикстуры, который мы сохранили с устройства в определенной версии, и мы делаем следующее, чтобы использовать его:
- (void)loadBundledRealmWithName:(NSString *)name;
{
[self deleteOnDiskRealm];
// copy over the file to the location
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *source = [[NSBundle bundleForClass:[self class]] pathForResource:name ofType:@"realm"];
if (documentsDirectory && source) {
NSString *destination = [documentsDirectory stringByAppendingPathComponent:kDefaultRealmFileName];
[[NSFileManager defaultManager] copyItemAtPath:source toPath:destination error:nil];
}
}
Тем не менее, между тестовыми случаями, без вызова RLMClearRealmCache
Похоже, что кэш Realm определяет, что миграции уже выполнены, хотя мы поменяли .realm
файл, и они должны быть запущены снова.
2 ответа
В итоге мы заставили Realm очистить кэш, используя тот факт, что он будет делать это, если на него больше не ссылаются. Было немного сложно отследить проблему, не позволяя ей сделать это: мы сохраняли ссылку на объект Realm между тестовыми прогонами:
context(@"some context", ^{
__block MyRealmObject *whoops;
beforeEach(^{
[specHelper loadBundledRealmWithName:@"release-50-fixture.realm"];
[migrationManager performMigrations];
whoops = [[MyRealmObject allObjects] firstObject];
});
it(@"first", ^{
// migrations will run for this `it`
});
it(@"second", ^{
// migrations will NOT run for this `it` since the old Realm is still around and its cache thinks migrations have already run (even though we've swapped out the backing DB).
// the issue is that `whoops` is retaining a `MyRealmObject` and thus the Realm.
});
});
Вы можете использовать отдельную область памяти для каждого теста. Когда вы делаете это, каждый тест получает "свежую" область, и состояние области не переходит от одного теста к другому.
Чтобы добиться этого, все что вам нужно, это установить Конфигурацию Царства. inMemoryIdentifer
на имя текущего теста перед его запуском. Вы можете сделать это в своем XCTestCase
подкласс setUp
метод (как предложено в документации области):
override func setUp() {
super.setUp()
Realm.Configuration.defaultConfiguration.inMemoryIdentifier = self.name
}
РЕДАКТИРОВАТЬ:
Этот ответ не подходит для обновленного вопроса, но я все равно оставлю его здесь, потому что он может помочь другим в поиске способа сброса состояния Realm между тестами.