2017-07-01 7 views
0

iOS 10のSwift 3アプリケーションでは、NotificationControllerを使用してViewControllerをテストしようとしています。スウィフトユニットテストでは、アプリケーションとユニットテストターゲット間のクラスキャストエラーが発生しました

私のViewControllerの初期化では、プロバイダーにデータを照会し、同期応答を受信します。プロバイダは、Webへの非同期呼び出しを使用してデータを更新しようとし、変更された場合、ViewControllerによってキャッチされる通知を送信します。ここに私のViewControllerの初期の作品である:

class func instantiateWithId(_ id: String, provider: DataProvider) -> MyViewController { 

    let storyboard = UIStoryboard(name: "Main", bundle: Bundle(for:MyViewController.self)); 
    let controller = storyboard.instantiateViewController(withIdentifier: "ViewControllerId") as! MyViewController; 

    controller.dataProvider = provider; 
    controller.objectId = id; 
    controller.object = controller.dataProvider!.getObject(id: id, completion: controller.refreshObject); 

    return controller; 
} 

初期化の後、私は正常に動作して通知オブザーバを登録します。

NotificationCenter.default.addObserver(self, selector: #selector(self.catchNotification), name: NotificationName, object: nil); 

ここでのViewControllerに通知を処理する機能があります。正常に動作している:

func catchNotification(notification: NSNotification) -> Void { 

    guard (notification.name == NotificationName) else {return;} 
    let info = notification.userInfo as! [String: Any]; 
    if info.count > 0 { 

     guard (info[objectId] != nil) else {return;} 
     if let value = info[objectId] as! MyCustomStruct? { 
      self.refreshData(updated: value); 
     } 
    } 
} 

をプロバイダでは、私は、Webからの非同期応答を受け取るとすぐに、私はのUserInfoに新しいデータで通知を送信:

var dict = Dictionary<String, myCustomStruct>(); 
dict.updateValue(newData, forKey: newData.objectId); 

let msg = Notification(name: NotificationName, object: nil, userInfo: dict) 
NotificationCenter.default.post(msg); 

すべてのコードは上記の作業をしています罰金、しかし、私のユニットテストで私は通知がunittestのターゲットのためのmyCustomStructは、アプリケーション・ターゲットにmyCustomStructにキャストすることができないことを言って、私のViewControllerでcatchedされたエラーを取得:

Could not cast value of type ‘ApplicationUnitTests.MyCustomStruct’ (0x1161fa828) to ‘Application. myCustomStruct' (0x1057fd6d0). 

私はすでにチェックしており、CustomStructは2つのターゲットで利用可能です。

func testViewControllerInitialization() { 
    let fixture = MockDataProvider(); 
    let sutId = fixture.testId; 
    let sut = MyViewController.instantiateWithId(sutId, provider: fixture) 

    _ = sut.view; 
    XCTAssertNotNil(sut, "SUT not initialized"); 
    XCTAssertNotNil(sut.object, "Object Not Loaded!"); 
    XCTAssertEqual(sutId, sut.object!.objectId, "Differente ObjectId expected!"); 

    let newValue = "changed"; 
    var nextFixture = fixture.getObject(objectId: sutId, completion: {(result) in return;}); 
    nextFixture.name = newValue; 

    fixture.refreshObject(newData: nextFixture); <- This function send the notification 
    sleep(1); 
    XCTAssertEqual(newValue, sut.object!.name); 
} 
+1

このエラーは完全に問題を記述しています:appは 'Application.myCustomStruct'を期待し、' ApplicationUnitTests.MyCustomStruct'を送信しています。テストで 'Application.myCustomStruct'を使用できませんか? –

+0

ポイントは:私はApplicationUnitTests.MyCustomStructsを持っていません。私はちょうどApplication.myCustomStructを持っています。私が理解しているように、ApplicationUnitTestsターゲットはすべてのApplication Targetクラスをインポートします。テストターゲットでクラスを複製する必要がある場合は、ユニットテストの全体的な考え方が失われます。 –

+0

アプリケーションファイル(およびそれに含まれるクラスと他のタイプ)は、ユニットテストターゲットに自動的にインポートされません。新しいファイルを作成するときに、そのファイルの対象となるターゲットを指定します。単体テストターゲットを追加しない場合は、後でインスペクタから追加することができます(ファイルを選択し、インスペクタを開き、テストターゲットをチェックします)。 –

答えて

0

[OK]を、任意の応答なしの長い研究の後、私は「が見つかり」私の問題の解決策:

は、ここに私のテストです。 thisの情報を使用して私はいくつかのサルのビジネスの事をtryedとエラーがなくなってしまった。

実際、問題を解決するのは、私のメインストーリーボードをUnitTestターゲットとして無効にすることでした。私はそれがinstantiateWithIdの方法の質問に記載されているために有効にしました。私の理解しているように、テストターゲットによって使用されるコードでそれをインスタンス化するには、テストターゲットにリンクする必要がありますが、なんらかの理由でこれは間違ったことでした。

これで動作しており、私はSwift TDDを続けることができます。しかし、誰かが私になぜテストが正しい構成なのかを私に説明してもらえれば、私は次の子供のためにあなたの名前を言います。

ありがとうございます。

+0

実際、私のコードはUnitTestTargetにリンクされていないため、メインストーリーボードが見つからないため、TDDを続行できません。私はそれが起こる可能性があると思ったように、それが最初からリンクした理由です。 –

関連する問題