Ios 在后台进程中使用模拟核心数据容器

Ios 在后台进程中使用模拟核心数据容器,ios,swift,unit-testing,core-data,Ios,Swift,Unit Testing,Core Data,我用使用核心数据的Swift iOS应用程序实现了单元测试,但我在通过单元测试方面遇到了困难。我引用了下面链接的指南和一些堆栈溢出线程,但仍然有问题 该应用程序在实际构建时运行时没有缺陷,但测试失败了,这让我相信我在集成模拟核心数据容器和后台持久性容器时弄糟了。然而,我似乎不知道我在这里错在哪里,所以任何建议都是非常感谢的 我很抱歉,如果我的帖子缺少任何关键细节,但我会在必要时添加它们 主要参考资料: 测试代码 控制器类 类测量控制器{ //标记:-属性 // 私有let persistentC

我用使用核心数据的Swift iOS应用程序实现了单元测试,但我在通过单元测试方面遇到了困难。我引用了下面链接的指南和一些堆栈溢出线程,但仍然有问题

该应用程序在实际构建时运行时没有缺陷,但测试失败了,这让我相信我在集成模拟核心数据容器和后台持久性容器时弄糟了。然而,我似乎不知道我在这里错在哪里,所以任何建议都是非常感谢的

我很抱歉,如果我的帖子缺少任何关键细节,但我会在必要时添加它们

主要参考资料:

测试代码 控制器类
类测量控制器{
//标记:-属性
//
私有let persistentContainer:NSPersistentContainer!
私有变量fetchedResultsController:NSFetchedResultsController!
lazy var backgroundMOC:NSManagedObjectContext={
返回self.persistentContainer.newBackgroundContext()
}()
//默认情况下设置为标准持久性容器
init(时态:tense,persistentContainer:NSPersistentContainer){
self.persistentContainer=persistentContainer
self.persistentcainer.viewContext.automaticallyMergesChangesFromParent=true
重新加载所有本地数据(for:tense)
}
便利初始化(时态:时态){
让appDelegate=UIApplication.shared.delegate作为?appDelegate else{
fatalError(“无法设置托管对象上下文”)
}
init(时态:tense,persistentContainer:appDelegate.persistenceContainer)
}
func getMealCount()->Int{
返回fetchedResultsController.FetchedObject?计数??0
}
func getfine(在indexPath:indexPath)->fine{
返回fetchedResultsController.object(位于:indexPath)
}
//布尔值决定是显示历史数据还是显示未来数据
func重新加载所有本地数据(对于时态:tense){
let fetchRequest:NSFetchRequest=deal.fetchRequest()
//设置谓词等。
//
fetchedResultsController=NSFetchedResultsController(fetchRequest:fetchRequest,managedObjectContext:backgroundMOC,sectionNameKeyPath:nil,cacheName:nil)//是否向此添加缓存?
做{
请尝试fetchedResultsController.performFetch()
}捕捉错误{
//
}
}
//拯救
func SAVELOCALMEIN(mealType:Int16,date:NSDate,mealDescription:String,servings:Int16,image:UIImage?,收藏:Bool,注释:String?=nil,recipeUID:String?=nil)->MEIN{
//制作新餐标
let-mean=mean(实体:mean.entity(),insertInto:backgroundMOC)
//调用helper func和result
返回保存(上下文:backgroundMOC,膳食:膳食,膳食ID:nil,膳食类型:膳食类型,日期:日期,膳食描述:膳食描述,服务:服务,图像:图像,收藏夹:收藏夹,注释:注释,收件人ID:recipeUID)
}
私有函数保存(上下文:NSManagedObjectContext,膳食:膳食,膳食ID:String?,膳食类型:Int16,日期:NSDate,膳食描述:String,服务:Int16,图像:UIImage?,收藏夹:Bool,注释:String?=nil,recipeUID:String?=nil)->膳食{
//设置属性
//        
做{
试试backgroundMOC.save()
回餐
}将let错误捕获为NSError{
打印(“无法保存。\(错误)”)
归零
}
}
class MealTests: XCTestCase {
var sut: MealController!

lazy var managedObjectModel: NSManagedObjectModel = {
    let managedObjectModel = NSManagedObjectModel.mergedModel(from: [Bundle(for: type(of: self))])!
    return managedObjectModel
}()

lazy var mockPersistentContainer: NSPersistentContainer = {
    let container = NSPersistentContainer(name: "WeeklyModel", managedObjectModel: self.managedObjectModel)
    let description = NSPersistentStoreDescription()
    description.type = NSInMemoryStoreType
    description.shouldAddStoreAsynchronously = false

    container.persistentStoreDescriptions = [description]
    container.loadPersistentStores {(description, error) in
        //Double check to confirm that date store is in memory
        precondition(description.type == NSInMemoryStoreType)

        //Check for errors
        if let error = error {
            fatalError("Creating an in-memory coordinator failed")
        }
    }
    return container
}()

override func setUp() {
    super.setUp()

    sut = MealController(tense: .all, persistentContainer: mockPersistentContainer)
}


func test_CreatingNewMeal_IsNotNilAndPropertiesSetCorrectly() {
    let mealType = Int16(1)
    let date = NSDate(timeIntervalSinceNow: 0.0)
    let mealDescription = "Testy McTestFace"
    let servings = Int16(1)
    let image = UIImage(named: "Recipe")
    let favorite = false

    let meal = sut.saveLocalMeal(mealType: mealType, date: date, mealDescription: mealDescription, servings: servings, image: image, favorite: favorite)

    //Test meal is not nil
    XCTAssertNotNil(meal, "Should not be nil")

    //Testing creating meal sets all properties correctly
    XCTAssertEqual(meal?.meal, mealType)
}
class MealController {

//MARK: - Properties
//<...>

private let persistentContainer: NSPersistentContainer!

private var fetchedResultsController: NSFetchedResultsController<Meal>!

lazy var backgroundMOC: NSManagedObjectContext = {
    return self.persistentContainer.newBackgroundContext()
}()

 //Set to standard persistence container by default
init(tense: Tense, persistentContainer: NSPersistentContainer) {
    self.persistentContainer = persistentContainer
    self.persistentContainer.viewContext.automaticallyMergesChangesFromParent = true

    reloadAllLocalData(for: tense)
}

convenience init(tense: Tense) {
    guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
        fatalError("Could not set Managed Object Context")
    }
    self.init(tense: tense, persistentContainer: appDelegate.persistenceContainer)
}

func getMealCount() -> Int {
    return fetchedResultsController.fetchedObjects?.count ?? 0
}

func getMeal(at indexPath: IndexPath) -> Meal {
    return fetchedResultsController.object(at: indexPath)
}

//The boolean determines whether historical or future data is shown
func reloadAllLocalData(for tense: Tense){
    let fetchRequest: NSFetchRequest<Meal> = Meal.fetchRequest()

    //Setting predicate, etc.
    //<...>

    fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: backgroundMOC, sectionNameKeyPath: nil, cacheName: nil)//Add cache to this?

    do {
        try fetchedResultsController.performFetch()
    } catch let error {
            //<...>
    }
}

//Saving

func saveLocalMeal(mealType: Int16, date: NSDate, mealDescription: String, servings: Int16, image: UIImage?, favorite: Bool, comment: String? = nil, recipeUID: String? = nil) -> Meal? {

    //Make new meal object
    let meal = Meal(entity: Meal.entity(), insertInto: backgroundMOC)

    //Call helper func and result result
    return save(context: backgroundMOC, meal: meal, mealUID: nil, mealType: mealType, date: date, mealDescription: mealDescription, servings: servings, image: image, favorite: favorite, comment: comment, recipeUID: recipeUID)
}

private func save(context: NSManagedObjectContext, meal: Meal, mealUID: String?, mealType: Int16, date: NSDate, mealDescription: String, servings: Int16, image: UIImage?, favorite: Bool, comment: String? = nil, recipeUID: String? = nil) -> Meal? {

    //Setting properties
    //<...>        

    do {
        try backgroundMOC.save()
        return meal
    } catch let error as NSError {
        print("Could not save. \(error)")
        return nil
    }
}