swift - 如何调整我的视图模型以实现依赖注入 swiftui(用于以后的单元测试)
问题描述
目前我有多个 ViewModel,在阅读了一些其他帖子并获得了帮助之后,我被建议在我的班级中实现依赖注入,以便对我的逻辑进行单元测试。
但是我不确定如何使我的以下类适应依赖注入,并且我不确定是否也需要更改我的 DataManager 类。
这是我的 ViewModel 的一个示例:
class CalorieProgressViewModel: ObservableObject {
@Published var calorieProgress = [CalorieProgressEntity]()
init() {
}
//Creating the data
func addCalorieProgressData(id: UUID, calorieProgress: Double, fatProgress: Double, carbProgress: Double, proteinPogress: Double, created: Date) {
CoreDataManager.shared.addCalorieProgressData(id: id, calorieProgress: calorieProgress, fatProgress: fatProgress, proteinProgress: proteinPogress, carbProgress: carbProgress, created: created){ (isAdded, error) in
if let error = error {
print(error)
} else {
print("Data has been added from addCalorieProgress VM")
}
}
}
如您所见,我只是使用 datamanger 类将数据添加到我的核心数据:
import Foundation
import UIKit
import CoreData
class CoreDataManager {
static let shared: CoreDataManager = {
let appDelegate = AppDelegate.instance!
let instance = CoreDataManager(managedObjectContext: appDelegate.persistanceContainer.viewContext)
return instance
}()
var managedContext: NSManagedObjectContext
private init(managedObjectContext: NSManagedObjectContext) {
managedContext = managedObjectContext
}
}
//MARK:- CalorieTracker Insert/Update/Delete
extension CoreDataManager {
func addCalorieProgressData(id: UUID, calorieProgress: Double, fatProgress: Double, proteinProgress: Double, carbProgress: Double, created: Date, completionHandler: @escaping (_ succeed: Bool, _ error: Error?) -> Void) {
let calorieProgressEntity = NSEntityDescription.insertNewObject(forEntityName: "CalorieProgressEntity", into: managedContext) as? CalorieProgressEntity
calorieProgressEntity?.id = id
calorieProgressEntity?.calorieProgress = calorieProgress
calorieProgressEntity?.fatProgress = fatProgress
calorieProgressEntity?.proteinProgress = proteinProgress
calorieProgressEntity?.carbProgress = carbProgress
calorieProgressEntity?.created = created
do {
try managedContext.save()
print("context saved for add calorieGoal")
completionHandler(true, nil)
} catch let error {
completionHandler(false, error)
}
}
func fetchCalorieProgressData(completionHandler: @escaping (_ succeed: Any?, _ error: Error?) -> Void) {
var goals = [CalorieProgressEntity]()
let calorieGoalRequest: NSFetchRequest<CalorieProgressEntity> = NSFetchRequest<CalorieProgressEntity>(entityName: "CalorieProgressEntity")
do {
goals = try managedContext.fetch(calorieGoalRequest)
completionHandler(goals, nil)
} catch let error {
completionHandler(nil, error)
}
}
}
任何帮助将不胜感激 :)
解决方案
Swift 中有不同的依赖注入方式。您可以通过 来完成init()
,然后在创建 ViewModel 时传递您的 CoreDataManager。
class CalorieProgressViewModel: ObservableObject {
@Published var calorieProgress = [CalorieProgressEntity]()
let manager: CoreDataManager
init(manager: CoreDataManager) {
self.manager = manager
}
//Creating the data
func addCalorieProgressData(id: UUID, calorieProgress: Double, fatProgress: Double, carbProgress: Double, proteinPogress: Double, created: Date) {
//<< here don't use your singleton, instead use the manager injected via dependency injection
manager.addCalorieProgressData(id: id, calorieProgress: calorieProgress, fatProgress: fatProgress, proteinProgress: proteinPogress, carbProgress: carbProgress, created: created){ (isAdded, error) in
if let error = error {
然后,当您创建 ViewModel 时,您会将 CoreDataManager 作为参数传递。在这里你可以使用你的 Singleton。
我建议为 CoreDataManager 创建一个协议。然后您可以轻松地将您的 MockManager 或实际的 CoreDataManager 传递到 ViewModel 以便稍后对其进行测试。
protocol CoreDataManager {
func addCalorieProgressData(id: UUID, calorieProgress: Double, fatProgress: Double, proteinProgress: Double, carbProgress: Double, created: Date, completionHandler: @escaping (_ succeed: Bool, _ error: Error?) -> Void)
}
class MainCoreDataManager: CoreDataManager {
...
class MockCoreDataManager: CoreDataManager {
... mocked here
推荐阅读
- python - 如何使用python创建一个函数
- sass - 我有以下 gulpfile.js,我正在通过命令行 gulp 消息执行它:
- javascript - 如何在javascript的内置构造函数中接受两个参数
- dpdk - 如何接收 40Gbps 线速流量零损耗?
- java - 未找到 Discord Bot Java (Maven) 库,加载失败 (com.sedmelluq / lavaplayer)
- testing - 空手道为肥皂请求返回 HTTP 415
- python - 无法通过 pip install 安装 binance 包
- android - 附近连接开发的问题
- php - 电子商务中的商家员工?
- c# - 将具体实现类型转换为通用接口类型