编写Core Data Budget类同名检测测试时遇异常问题
问题解决方法
核心问题分析
你遇到的问题根源有两个:
- Core Data的
NSFetchRequest默认会包含当前context中未保存的内存对象,所以刚创建的Budget实例会被exists函数检测到,导致第一次调用save就触发重复异常。 - 你的
save方法里调用try save()会无限递归调用自身,最终会引发栈溢出错误。
解决方案步骤
1. 修复exists函数,排除未保存的内存对象
修改exists方法,给fetch请求添加includesPendingChanges = false配置,让查询只读取持久化存储中的数据,忽略context里未保存的临时对象:
private func exists(_ name: String) throws -> Bool { let request = Budget.fetchRequest() request.predicate = NSPredicate(format: "name = %@", name) request.sortDescriptors = [] request.includesPendingChanges = false // 关键配置:仅查询已持久化的数据 let budgets = try viewContext.fetch(request) return !budgets.isEmpty }
2. 修复save方法的无限递归问题
将save方法中调用的try save()改为调用父类的save方法,避免无限递归:
override func save() throws { if try exists(name ?? "") { throw BudgetError.duplicateName } else { try super.save() // 调用父类的save方法,而非自身 } }
3. 优化测试代码
移除不必要的refreshAllObjects调用(会重置未保存的对象属性),测试代码修改为:
func test_Throws_Duplicate_Name_Exception() throws { var thrownError: Error? let budget = Budget(context: CoreDataProvider.shared.viewContext) budget.name = "Car Rental" try budget.save() // 第一次save成功 // 再次调用save,验证是否抛出重复异常 XCTAssertThrowsError(try budget.save()) { thrownError = $0 } XCTAssertEqual(thrownError as? BudgetError, .duplicateName) }
内容的提问来源于stack exchange,提问作者john doe
相关产品推荐
相关产品推荐

