你好,
我正在尝试对 SwiftData 模型进行单元测试,但我面临着一个奇怪的情况,并且找不到问题的答案。
我向您展示的第一个解决方案不起作用,第二个解决方案有效。
首先,这是我的@Model:
@Model
class Movie {
var name: String
init(name: String) {
self.name = name
}
}
第一个解决方案(不起作用):
var modelContainer: ModelContainer {
do {
let container = try ModelContainer(for: Movie.self, configurations: ModelConfiguration(isStoredInMemoryOnly: true))
return container
} catch {
fatalError("Failed to create container.")
}
}
@MainActor
final class Tests: XCTestCase {
private var context: ModelContext!
override func setUp() {
context = modelContainer.mainContext
}
func testCountShouldBeOne() {
let movie = Movie(name: "NewMovie")
context.insert(movie) // Thread 1: EXC_BREAKPOINT
do {
let descriptor = FetchDescriptor<Movie>()
let movies = try context.fetch(descriptor)
XCTAssertEqual(movies.count, 1)
} catch {
XCTFail()
}
}
}
第二个解决方案(有效):
(modelContainer remains the same)
@MainActor
final class Tests: XCTestCase {
private var container: ModelContainer!
override func setUp() {
container = modelContainer
}
func testCountShouldBeOne() {
let movie = Movie(name: "NewMovie")
container.mainContext.insert(movie)
do {
let descriptor = FetchDescriptor<Movie>()
let movies = try container.mainContext.fetch(descriptor)
XCTAssertEqual(movies.count, 1)
} catch {
XCTFail()
}
}
}
所以区别在于我现在必须调用container.mainContext来进行SwiftData操作,并且它可以工作,但是在第一个解决方案中,我有:context.something,我得到了EXC_BREAKPOINT。
有人知道为什么吗?
谢谢你!
在这两种情况下,
modelContainer
都是一个计算属性,当您访问它时,它总是返回一个newModelContainer
。
在第一种情况下,您只需将
modelContext
从 ModelContainer
中取出,而不握住 ModelContainer
。结果,ModelContainer
被释放,现在只剩下一个没有关联容器的 ModelContext
。
在第二种情况下,您do将
ModelContainer
存储为Tests
类的存储属性,因此测试用例使其保持活动状态。
用于访问模型上下文的确切语法并不真正相关。这里的关键点是您是否保持计算属性返回的
ModelContainer
处于活动状态。如果你觉得 container.mainContext
太长,你可以在 Tests
类中编写这样的计算属性。
var modelContext: ModelContext { container.mainContext }