我们在尝试测试处理Realm对象的特定方法时遇到问题。
这是测试方法
func testMarkPhotoAsViewedMethodNonExistingIdentityPhotosContainer() {
let photoId = "id1"
let albumMembershipData = AlbumMembershipData(unsafeResultMap: albumMembershipsFixture.first!)
let rlmContainer = ViewedAlbumMembershipPhotosContainer()
rlmContainer.albumMembershipId = albumMembershipData.membershipDetails().id
let realm = try! Realm(configuration: realmConfig)
try! realm.write {
realm.add(rlmContainer)
}
try! service.markPhotoAsViewed(viewedPhotosContainer: rlmContainer,
selectedIdentitiesIdentityIds: ["identity1", "identity2"],
photo: ExtendedPhotoDetails(id: photoId),
photoSetType: .matches)
waitUntil(timeout: 10) { done in
var identityContainer1: ViewedIdentityPhotosContainer? = nil
var identityContainer2: ViewedIdentityPhotosContainer? = nil
while(true) {
identityContainer1 = self.service.getViewedPhotos(forIdentityId: "identity1")
identityContainer2 = self.service.getViewedPhotos(forIdentityId: "identity2")
if identityContainer1 != nil && identityContainer2 != nil {
break
}
}
expect(identityContainer1?.contains(photo: ExtendedPhotoDetails(id: photoId))) == true
expect(identityContainer2?.contains(photo: ExtendedPhotoDetails(id: photoId))) == true
done()
}
}
这是正在测试的方法:
public func markPhotoAsViewed(viewedPhotosContainer: ViewedAlbumMembershipPhotosContainer,
selectedIdentitiesIdentityIds: [String]?,
photo: ExtendedPhotoDetails,
photoSetType: AlbumPhotoSet) throws
{
log.verbose("⚙️ Marking photo \(photo.id) as viewed in photoset: \(photoSetType)")
let realm = try! Realm(configuration: configuration)
let threadSafeContainer = viewedPhotosContainer.toThreadConfinedObject(inRealm: realm) ?? viewedPhotosContainer
do {
try realm.write {
threadSafeContainer.addViewedPhoto(withPhotoId: photo.id, forPhotoSetType: photoSetType)
}
} catch {
log.error("❌ Error marking photo as viewed: \(error.localizedDescription)")
}
// If this a matched photo in the album, we need to mark any potential photos
// in the appropriate identity viewed photos container
guard let identityIds = selectedIdentitiesIdentityIds, photoSetType == .matches else { return }
let queue = isRunningUnitTests() ? DispatchQueue.main : DispatchQueue.global(qos: .background)
queue.async {
let realm = try! Realm(configuration: self.configuration)
for id in identityIds {
var identityContainer: ViewedIdentityPhotosContainer? = nil
if let container = realm.object(ofType: ViewedIdentityPhotosContainer.self, forPrimaryKey: id) {
log.verbose("ℹ️ Container for identity id \(id ) already exists, adding photo entry...")
identityContainer = container
} else {
log.verbose("ℹ️ Container for identity id \(id ) doesn't exist. Creating a new one...")
identityContainer = ViewedIdentityPhotosContainer()
identityContainer?.identityId = id
}
do {
try realm.write {
if !(identityContainer?.photoIds.contains(photo.id) ?? true) {
identityContainer?.photoIds.append(photo.id)
}
realm.add(identityContainer!, update: true)
}
} catch {
log.verbose("❌ Error appending photo \(photo.id) to identity container: \(id)")
}
}
}
}
这是获取Realm结果的便捷方法:
public func getViewedPhotos(forIdentityId identityId: String) -> ViewedIdentityPhotosContainer? {
let realm = try! Realm(configuration: configuration)
let predicate = NSPredicate(format: "identityId = %@", identityId)
return realm.objects(ViewedIdentityPhotosContainer.self).filter(predicate).first
}
看来,如果我们在运行测试时未在markPhotoAsViewed
方法中使用主队列,那么testMarkPhotoAsViewedMethodNonExistingIdentityPhotosContainer
将永远无法获取identityContainer1
和identityContainer2
。
我怀疑这与Nimble实施其waitUntil
方法的方式有关,但是我很想就纯粹出于教育目的为什么要这样做有一个明确的答案。
编辑:这是setUp()
上的领域配置:
realmConfig = Realm.Configuration.init(inMemoryIdentifier: self.name, deleteRealmIfMigrationNeeded: true)