La classe Foo est implémentée dans MyApp et MyAppTestCase. Un des deux sera utilisé. Lequel est indéfini

Récemment, j’ai commencé à tester mon application. Ce projet (dans Xcode4) a été créé sans kit de test unitaire, il a donc fallu le configurer. J’ai suivi les étapes à partir d’ici: http://cocoawithlove.com/2009/12/sample-mac-application-with-complete.html Et ça marchait bien pour les classes simples mais maintenant j’essaie de tester une classe qui dépend sur un autre et cela sur un autre, etc.

J’ai d’abord eu une erreur de l’éditeur de liens, donc j’ai ajouté des fichiers *.m à la cible du *.m de test, mais maintenant je reçois un avertissement pour chaque cours que je tente de tester:

La classe Foo est implémentée dans MyApp et MyAppTestCase. Un des deux sera utilisé. Lequel est indéfini.

Je me demande pourquoi? Comment puis-je resoudre ceci? Peut-être que j’ai manqué quelque chose lors de la définition de la cible de test unitaire?

Edit – La solution

  • Définissez “Bundle Loader” correctement sur $(BUILT_PRODUCTS_DIR)/AppName.app/AppName

  • Définissez “Symboles masqués par défaut” sur NO (dans les parameters de construction de l’application cible). C’est de là que viennent les erreurs du lieur car il est OUI par défaut! J’ai lutté avec ça pendant si longtemps!

Source: erreur de liaison pour les tests unitaires avec XCode 4?

La classe Foo est implémentée à la fois dans MyApp et MyAppTestCase. Un des deux sera utilisé. Lequel est indéfini.

Je me demande pourquoi?

car les deux images (l’application et le kit de test unitaire) définissent l’implémentation de la classe. la classe est chargée dynamicment dans l’environnement d’exécution objc. le runtime objc utilise un espace de noms plat. comment ça marche:

  • le binary est chargé, en commençant par ses dépendances
  • au fur et à mesure que chaque binary est chargé, les classes objc s’enregistrent avec le runtime objc
  • Si une classe avec un nom spécifique est chargée deux fois, le comportement est indéfini. une implémentation d’une classe (avec des noms identiques) peut être chargée dans le runtime objc.

Le problème typique ici est que vous serez renvoyé une implémentation – votre application va probablement tomber en panne lorsque le type est en conflit (lorsque la classe ne provient pas du même fichier source).

vous évitez généralement cela en renommant une classe ou en exportant la classe dans une image. renommer la classe ne s’applique évidemment pas à votre cas. vous avez un fichier Foo.m qui est compilé, exporté et chargé par deux images quand il devrait être en un.

Cela doit être interprété par vous comme une erreur de lieur de symboles en double. même si l’implémentation est le même fichier source (et que l’implémentation est la même) – c’est un problème que vous devez résoudre.

Comment puis-je resoudre ceci?

Si Foo.m est une classe de l’application, vous devez supprimer (ne pas comstackr et lier) Foo.m du test unitaire. Si cela fait partie du test unitaire, ne le comstackz pas et ne le liez pas à la cible de test unitaire.

Suivez ensuite les instructions de l’article pour lier / charger votre test unitaire à l’application. c’est dans cette zone générale de l’article: où “WhereIsMyMac” est le nom de l’application que vous testez. Cela permettra au lien cible du test de se connecter à l’application (vous n’obtenez donc pas d’erreurs de l’éditeur de liens lors de la compilation). La partie importante est que vos fichiers de test sont compilés dans la cible de test unitaire (uniquement) et que les classes de votre application sont compilées et liées à l’application. vous ne pouvez pas simplement les append – ils se lient et se chargent dynamicment.

Peut-être que j’ai manqué quelque chose lors de la définition de la cible de test unitaire?

De l’article que vous avez lié:

Remarque: La cible de test est une cible distincte. Cela signifie que vous devez faire attention à l’appartenance à la cible. Tous les fichiers sources d’application doivent être ajoutés à la cible de l’application uniquement. Les fichiers de code de test doivent être ajoutés à la cible de test uniquement.

La partie que vous avez mal comprise est probablement la phase de liaison et de chargement du paquet de test unitaire.

Si vous utilisez Cocoapods, votre podfile n’a besoin que des dépendances dans la section pour la cible principale, pas pour les cibles de test. Si vous ajoutez des dépendances en double pour les cibles de test, vous obtiendrez le message d’erreur de l’OP.

 target 'MyProject' do pod 'Parse' end target 'MyProjectTests' do end target 'MyProjectUITests' do end 

Pour moi, tout ce que j’avais à faire était de décocher la case qui fait de la classe Foo un membre de la cible de test unitaire. Il ne devrait pas être membre des deux cibles et devrait ressembler à ceci:

Abonnement cible

Si vous ne pouvez pas voir l’image, il s’agit d’une capture d’écran du volet “Abonnement cible” de Xcode. Il y a deux cibles: une avec une icône d’application “A” et le nom du test. L’autre est la cible de test d’unité et comporte une icône de test unitaire:

 Target Membership [X] Foo [ ] FooTests 

Pour moi, cela s’est produit parce que j’ai déployé sur l’appareil, puis sur le simulateur, car NSZombies est activé. La solution consistait à passer à la configuration du simulateur et à faire un produit -> Nettoyer, puis à passer à la configuration du périphérique et à faire de même. Une erreur s’est produite. C’est à faire avec le cache de compilation.

La raison en est que vous remplacez RUNPATH_SEARCH_PATHS du RUNPATH_SEARCH_PATHS de RUNPATH_SEARCH_PATHS de votre cible d’application défini dans une autre cible.

Solution:

Accédez à votre cible d’application et recherchez le RUNPATH_SEARCH_PATHS génération RUNPATH_SEARCH_PATHS et utilisez-y l’indicateur $(inherited) pour les deux: Debug et Release

Rencontrer les mêmes problèmes, ma situation est la classe NSNotification est implémentée dans /System/Library/Frameworks/Foundation.framework/Foundation, est-ce que n’importe quel mec est tombé sur le même problème, n’importe quelle direction ou conseil sera apprécié.