如何在测试之间重置 Realm 的状态?
How can I reset Realm's state between tests?
我们一直在使用 RLMClearRealmCache
清除正在测试迁移的测试之间的 Realm 状态。如果缓存没有被清除,下一个测试将不会执行迁移,因为缓存仍然报告架构是最新的,即使我们已经删除并替换了领域固定文件(它有一个旧架构)。
RLMClearRealmCache
最近被移动到 Objective-C++ 文件,所以我们想停止使用它并避免在我们的项目中使用 Objective-C++。这仍然是 best/only 的做法吗?
明确地说,我们没有为这些规范使用内存中的 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 的缓存确定迁移已经 运行,即使我们已经换掉了 [=15] =] 文件,他们需要再次 运行。
您可以为每个测试使用一个单独的内存中领域。当您这样做时,每个测试都会获得一个 "fresh" 领域,并且该领域的状态不会从一个测试泄漏到另一个测试。
要实现这一点,您只需将 Realm 的配置 inMemoryIdentifer
设置为 运行 之前的当前测试的名称。您可以在 XCTestCase
子类 setUp
方法中执行此操作(如 Realm 文档中所建议):
override func setUp() {
super.setUp()
Realm.Configuration.defaultConfiguration.inMemoryIdentifier = self.name
}
编辑:
这个答案不适合更新后的问题,但我还是会把它留在这里,因为它可能会帮助其他人寻找在测试之间重置 Realm 状态的方法。
我们最终让 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.
});
});
我们一直在使用 RLMClearRealmCache
清除正在测试迁移的测试之间的 Realm 状态。如果缓存没有被清除,下一个测试将不会执行迁移,因为缓存仍然报告架构是最新的,即使我们已经删除并替换了领域固定文件(它有一个旧架构)。
RLMClearRealmCache
最近被移动到 Objective-C++ 文件,所以我们想停止使用它并避免在我们的项目中使用 Objective-C++。这仍然是 best/only 的做法吗?
明确地说,我们没有为这些规范使用内存中的 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 的缓存确定迁移已经 运行,即使我们已经换掉了 [=15] =] 文件,他们需要再次 运行。
您可以为每个测试使用一个单独的内存中领域。当您这样做时,每个测试都会获得一个 "fresh" 领域,并且该领域的状态不会从一个测试泄漏到另一个测试。
要实现这一点,您只需将 Realm 的配置 inMemoryIdentifer
设置为 运行 之前的当前测试的名称。您可以在 XCTestCase
子类 setUp
方法中执行此操作(如 Realm 文档中所建议):
override func setUp() {
super.setUp()
Realm.Configuration.defaultConfiguration.inMemoryIdentifier = self.name
}
编辑:
这个答案不适合更新后的问题,但我还是会把它留在这里,因为它可能会帮助其他人寻找在测试之间重置 Realm 状态的方法。
我们最终让 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.
});
});