it-swarm.com.de

Die Klasse Foo ist sowohl in MyApp als auch in MyAppTestCase implementiert. Einer der beiden wird verwendet. Welches ist undefiniert

Vor kurzem habe ich mit dem Unit-Test meiner Anwendung begonnen. Dieses Projekt (in Xcode4) wurde ohne ein Unit-Test-Bundle erstellt, daher musste ich es einrichten. Ich habe die folgenden Schritte von hier aus befolgt: http://cocoawithlove.com/2009/12/sample-mac- application-with-complete.html Und es hat gut funktioniert für einfache Klassen, aber jetzt versuche ich, eine Klasse zu testen, die von einer anderen Klasse abhängt und von einer anderen, usw.

Zuerst bekam ich einen Linker-Fehler, also fügte ich *.m-Dateien zum Testfallziel hinzu, aber jetzt bekomme ich eine Warnung für jede Klasse, die ich zu testen versuche: 

Die Klasse Foo ist in MyApp .__ implementiert. und MyAppTestCase. Einer der beiden wird verwendet werden. Welches ist undefiniert.

Ich frage mich, warum das so ist. Wie kann ich das lösen? Vielleicht habe ich beim Festlegen des Gerätetestziels etwas verpasst?

Bearbeiten - Die Lösung

  • Setze "Bundle Loader" korrekt auf $(BUILT_PRODUCTS_DIR)/AppName.app/AppName

  • Setzen Sie "Standardmäßig ausgeblendete Symbole" auf NO (in den Build-Einstellungen der Zielanwendung). Dies ist, wo die Linker-Fehler stammen, weil es standardmäßig JA ist !. Ich habe so lange damit zu kämpfen !.

Quelle: Verbindungsfehler beim Komponententest mit XCode 4?

60
nacho4d

Die Klasse Foo ist sowohl in MyApp als auch in MyAppTestCase implementiert. Einer der beiden wird verwendet. Welches ist undefiniert.

Ich frage mich, warum das so ist.

weil beide Images (die App und das Unit-Test-Bundle) die Implementierung der Klasse definieren. Die Klasse wird dynamisch in die objc-Laufzeit geladen. Die Objc-Laufzeit verwendet einen flachen Namespace. wie das funktioniert:

  • die Binärdatei wird geladen, beginnend mit ihren Abhängigkeiten
  • wenn jede Binärdatei geladen wird, registrieren sich die Objc-Klassen bei der Objc-Laufzeit
  • wenn eine Klasse mit einem bestimmten Namen zweimal geladen wird, ist das Verhalten undefiniert. Eine Implementierung einer Klasse (mit identischen Namen) kann in die objc-Laufzeit geladen werden.

das Typical - Problem besteht hier darin, dass Sie eine Implementierung zurückgeben - Ihre App stürzt wahrscheinlich ab, wenn der Typ in Konflikt steht (wenn die Klasse nicht aus derselben Quelldatei stammt).

sie vermeiden dies normalerweise, indem Sie entweder eine Klasse umbenennen oder die Klasse in ein Bild exportieren. Das Umbenennen der Klasse trifft offensichtlich nicht auf Ihren Fall zu. Sie haben eine Datei Foo.m, die von zwei Bildern kompiliert, exportiert und geladen wird, wenn es sich in einem Bild befinden sollte.

dies sollte von Ihnen als doppelter Symbol-Linker-Fehler interpretiert werden. Obwohl die Implementierung dieselbe Quelldatei ist (und dieselbe Implementierung), müssen Sie das Problem beheben.

Wie kann ich das lösen?

wenn Foo.m eine Klasse der App ist, müssen Sie Foo.m aus dem Komponententest entfernen (nicht kompilieren und verknüpfen). Wenn es Teil des Komponententests ist, kompilieren Sie es nicht und verknüpfen Sie es nicht mit dem Komponententestziel.

befolgen Sie anschließend die Anweisungen im Beitrag zum Verknüpfen/Laden Ihres Gerätetests mit der App. Es ist in diesem allgemeinen Bereich des Beitrags: wobei "WhereIsMyMac" der Name der Anwendung ist, die Sie als Einheit testen. Dadurch wird das Testziel mit der Anwendung verknüpft (so dass beim Kompilieren keine Linker-Fehler auftreten). Der wichtige Teil ist, dass Ihre Testdateien (nur) in dem Komponententestziel kompiliert werden und die Klassen Ihrer App kompiliert und mit der App verknüpft werden. Sie können sie nicht einfach hinzufügen - sie werden dynamisch verknüpft und geladen.

Vielleicht habe ich beim Festlegen des Gerätetestziels etwas verpasst?

Aus dem Artikel, den Sie verlinkt haben:

Hinweis: Das Testziel ist ein separates Ziel. Dies bedeutet, dass Sie auf die Zielmitgliedschaft achten müssen. Alle Anwendungsquelldateien sollten nur dem Anwendungsziel hinzugefügt werden. Testcodedateien sollten nur dem Testziel hinzugefügt werden.

der fehlerhafte Teil ist wahrscheinlich die Verknüpfungs- und Ladephase des Komponententestbündels.

42
justin

Wenn Sie Cocoapods verwenden, benötigt Ihre Pod-Datei nur die Abhängigkeiten im Abschnitt für das Hauptziel, nicht die Testziele. Wenn Sie doppelte Abhängigkeiten für die Testziele hinzufügen, wird die Fehlermeldung des OP angezeigt.

target 'MyProject' do
pod 'Parse'

end

target 'MyProjectTests' do

end

target 'MyProjectUITests' do

end
15
Richard

Für mich musste ich nur das Kontrollkästchen deaktivieren, das die Foo-Klasse zum Mitglied des Komponententestziels macht. Es sollte nicht Mitglied beider Ziele sein und sollte folgendermaßen aussehen:

Target Membership

Falls Sie das Bild nicht sehen können, handelt es sich um einen Screenshot des Xcode-Bereichs "Zielmitgliedschaft". Es gibt zwei Ziele: eines mit einem Anwendungssymbol "A" und dem Testnamen. Das andere ist das Einheitstestziel und hat ein Einheitstestsymbol:

Target Membership
[X] Foo
[ ] FooTests
12
Steve HHH

Für mich ist dies passiert, weil ich das Gerät und dann den Simulator installiert habe, da NSZombies aktiviert ist. Die Lösung bestand darin, zur Simulatorkonfiguration zu wechseln und ein Produkt auszuführen -> Reinigen, dann zur Gerätekonfiguration zu wechseln und dasselbe zu tun. Fehler ging weg. Das hat mit dem Build-Cache zu tun.

3
Geoff H

Der Grund ist, dass Sie RUNPATH_SEARCH_PATHS der in einem anderen Ziel definierten Build-Einstellung Ihres App-Ziels überschreiben.

Lösung:

Gehen Sie zu Ihrem App-Ziel, suchen Sie nach RUNPATH_SEARCH_PATHS build und verwenden Sie dort $(inherited) für beide: Debug und Release

Kommen Sie zu den gleichen Problemen. Meine Situation ist, dass die Klasse NSNotification in beiden Systemen /Library/Frameworks/Foundation.framework/Foundation implementiert ist. Wenn ein Typ auf das gleiche Problem stößt, werden Anweisungen oder Ratschläge angesprochen.

0
suxinde2009