Как я могу сбросить состояние 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 между тестами.

Другие вопросы по тегам