2017-09-21 25 views
0

我想寫一個測試,以確保我的視圖模型的模型屬性,當設置從模型調用我的fetchPlan方法,然後在我的視圖模型中設置我的'計劃'屬性。這似乎是設置屬性,但缺少值...單元測試DI與CoreData不會工作

這裏是我的視圖模型

final class PlanProgressViewModel: PlanProgressViewModelView { 

// MARK: - Properties 
fileprivate var plan: PlanData? 

// MARK: - PlanProgressViewModelView 
weak var viewDelegate: PlanProgressViewModelViewDelegate? 

var model: PlanModel? { 
    didSet { 
     model?.fetchCurrentPlan(completionHandler: { (plan) in 
      guard let plan = plan else {return} 
      self.plan = plan 
     }) 
    } 
} 
// Testing this fails... 
var planName: String! { 
    guard let plan = plan else {return "No plan"} 
    return plan.name 
} 

var planProgressionString: String! { 
    return "\(Int(round(self.progress * 100)))%" 
} 

var progress: Double! { 
    guard let plan = plan, let workouts = plan.workouts, let completedWorkouts = plan.completedWorkouts else {return 0} 
    return Double(Int(completedWorkouts)/workouts.count) 
} 
} 

這裏是我的測試套件,我使用的是模擬從模型返回硬編碼數據。

var sut: PlanProgressViewModel! 
var model: MockPlanModel! 
var moc: NSManagedObjectContext! 

override func setUp() { 
    super.setUp() 
    moc = setupInMemoryMOC() 

    let mockModel = MockPlanModel(moc: moc) 
    model = mockModel 

    let viewModel = PlanProgressViewModel() 
    viewModel.model = model 
    sut = viewModel 
} 

override func tearDown() { 
    moc = nil 
    model = nil 
    sut = nil 
    super.tearDown() 
} 
// This passes 
func testModelFetchesCurrentPlanOnce() { 
    XCTAssertEqual(model.fetchPlanWasCalled, 1) 
} 

// This is failing 
func testPlanName() { 
    XCTAssertEqual(sut.planName, "Test plan") 
} 

這是我設立一個在內存中的持久性存儲方法...

public func setupInMemoryMOC() -> NSManagedObjectContext { 
let mom = NSManagedObjectModel.mergedModel(from: [Bundle.main]) 
let psc = NSPersistentStoreCoordinator(managedObjectModel: mom!) 

do { 
    try psc.addPersistentStore(ofType: NSInMemoryStoreType, configurationName: nil, at: nil, options: nil) 
} catch { 
    fatalError() 
} 

let moc = NSManagedObjectContext.init(concurrencyType: .mainQueueConcurrencyType) 
moc.persistentStoreCoordinator = psc 

return moc } 

這是我爲返回硬編碼數據對模型進行模擬......

public class MockPlanModel: MWPlanModel { 
var fetchPlanWasCalled = 0 

override public func fetchCurrentPlan(completionHandler: @escaping (_ plan: PlanData?) ->()) { 
    fetchPlanWasCalled += 1 

    let moc = setupInMemoryMOC() 
    let plan = createTestPlan(moc: moc) 

    completionHandler(plan) 
}} 

這裏是我的用於創建模型對象的輔助方法(PlanData是我的'Plan'NSManaged對象繼承的協議)。

public func createTestPlan(moc: NSManagedObjectContext) -> PlanData { 
let plan: Plan = Plan(context: moc) 
plan.name = "Test plan" 
plan.completedWorkouts = 5 
plan.currentPlan = true 

for _ in 0..<5 { 
    plan.mutableOrderedSetValue(forKeyPath: #keyPath(Plan.workouts)).add(createTestCompletedWorkout(moc: moc)) 
} 

return plan } 

計劃名稱應該是「測試計劃」,因爲這是我設置的硬編碼值爲但失敗並返回一個空字符串,而不是... enter image description here

很堅持這一點,我是相當新的測試,所以我很感激任何幫助。由於

+0

你會檢查我的更新答案,並讓我知道 –

回答

0

@MartinR評論好點出:

左側"Test plan"非可選被自動提升爲可選。因爲sut.planName是可選的。更多檢查這個Swift comparing Strings optionals vs non-optional

你需要解開sut.planName

if let planName = sut.planName{ 
    XCTAssertEqual(planName, "Test plan") 
} 

或者試試這樣:

XCTAssertEqual((sut.planName ?? ""), "Test plan") 

注意:如果你的臉還是同樣的問題,然後更新您的Xcode

// Using Apple XCTest (Xcode 7.3.1), this produces the output: 
// "XCTAssertEqual failed: ("Optional(1)") is not equal to ("Optional(2)") - " 
XCTAssertEqual(1, 2) 

更多詳細信息:Here Bug reported

+0

嗨,感謝您的答案。我沒有意識到這可能是一個潛在的問題,所以謝謝。然而,它仍然失敗,但這次,而不是一個可選類型,它只是返回一個空字符串。我安全地解開它,我也更新了我的Xcode,但仍然無法正常工作。 –

+0

然後請檢查您的其他相關代碼。 –