web-dev-qa-db-fra.com

Class Foo est implémenté dans MyApp et MyAppTestCase. Un des deux sera utilisé. Lequel n'est pas défini

Récemment, j'ai commencé à tester mon application. Ce projet (dans Xcode4) a été créé sans un ensemble de tests unitaires, donc je devais le configurer . J'ai suivi les étapes à partir d'ici: http://cocoawithlove.com/2009/12/sample-mac- application-with-complete.html Et cela fonctionnait bien pour des classes simples, mais maintenant, j'essaie de tester une classe qui dépend d'une autre et que d'une autre, etc.

Tout d'abord, j'ai eu une erreur de l'éditeur de liens. J'ai donc ajouté des fichiers *.m à la cible de test, mais maintenant, un avertissement s'affiche pour chaque classe que j'essaie de tester: 

Class Foo est implémenté dans MyApp et MyAppTestCase. L'un des deux sera être utilisé. Lequel n'est pas défini.

Je me demande pourquoi c'est ça? Comment puis-je résoudre ça? Peut-être ai-je oublié quelque chose lors de la définition de l'objectif de test unitaire?

Edit - La solution

  • Réglez "Bundle Loader" correctement sur $(BUILT_PRODUCTS_DIR)/AppName.app/AppName

  • Définissez "Symboles masqués par défaut" sur NO (dans les paramètres de construction de l'application cible). C’est d’où viennent les erreurs de l’éditeur de liens car c’est OUI par défaut !. Je lutte avec ça depuis si longtemps!.

Source: Erreur de liaison lors des tests unitaires avec XCode 4?

60
nacho4d

Class Foo est implémenté dans MyApp et MyAppTestCase. Un des deux sera utilisé. Lequel n'est pas défini.

Je me demande pourquoi c'est ça?

car les deux images (l’application et l’ensemble de tests unitaires) définissent l’implémentation de la classe. la classe est chargée dynamiquement dans le runtime objc. le runtime objc utilise un espace de noms plat. comment ça marche:

  • le binaire est chargé, en commençant par ses dépendances
  • à chaque chargement, les classes objc s'enregistrent avec le runtime objc
  • si une classe portant un nom spécifique est chargée deux fois, le comportement n'est pas défini. une implémentation d'une classe (avec des noms identiques) peut être chargée dans le runtime objc.

le problème typique de est qu’il vous sera renvoyé une implémentation - votre application va probablement planter en cas de conflit de type (lorsque la classe ne provient pas du même fichier source).

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

cela doit être interprété par vous comme une erreur de duplicateur de symbole dupliqué. Même si l'implémentation est le même fichier source (et l'implémentation est la même), il s'agit d'un problème que vous devez résoudre.

Comment puis-je résoudre ça?

si Foo.m est une classe de l'application, vous devez supprimer (ne pas compiler et lier) Foo.m du test unitaire. si cela fait partie du test unitaire, ne le compilez pas et ne le liez pas à la cible du test unitaire.

ensuite, suivez les instructions dans le post 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 à l'unité. Cela permettra à la cible de test de se lier à l’application (pour éviter les erreurs d’éditeur de liens lors de la compilation). l’important est que vos fichiers de test soient compilés dans la cible de test unitaire (uniquement), et que les classes de votre application soient compilées et liées à l’application. vous ne pouvez pas simplement les ajouter - ils se lient et se chargent dynamiquement.

Peut-être ai-je oublié quelque chose lors de la définition de l'objectif 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'adhésion cible. Tous les fichiers source de l'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 sur laquelle vous vous êtes trompé est probablement les phases de liaison et de chargement de l'ensemble de tests unitaires.

42
justin

Si vous utilisez Cocoapods, votre podfile n'a besoin que des dépendances de la section pour la cible principale, pas des 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
15
Richard

Pour moi, il me suffisait de décocher la case permettant à la classe Foo de devenir membre de la cible de test unitaire. Il ne devrait pas être un membre des deux cibles, et devrait ressembler à ceci:

Target Membership

Si vous ne pouvez pas voir l'image, c'est une capture d'écran du volet "Adhésion à la cible" de Xcode. Il y a deux cibles: l'une avec une icône d'application "A" et le nom du test. L'autre est la cible de test unitaire, et comporte une icône de test unitaire:

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

Pour moi, cela est dû au fait que je me suis déployé sur le périphérique, 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 dispositif et à faire de même. L'erreur est partie. C'est à voir avec le cache de construction.

3
Geoff H

La raison en est que vous remplacez RUNPATH_SEARCH_PATHS du paramètre de construction de votre cible d'application défini dans une autre cible.

Solution:

Accédez à votre cible d'application et recherchez le paramètre de construction RUNPATH_SEARCH_PATHS et utilisez son indicateur $(inherited) pour les deux: Debug et Release

2

Je rencontre les mêmes problèmes, ma situation est que la classe NSNotification est implémentée à la fois dans/System/Library/Frameworks/Foundation.framework/Foundation, y a-t-il un mec qui rencontre le même problème?.

0
suxinde2009