Класс Foo реализован как в MyApp, так и в MyAppTestCase. Один из двух будет использован. Какой из них не определен - PullRequest
62 голосов
/ 27 мая 2011

Недавно я начал модульное тестирование своего приложения. Этот проект (в Xcode4) был создан без пакета модульного тестирования, поэтому мне пришлось его настроить. Я следовал за шагами отсюда: http://cocoawithlove.com/2009/12/sample-mac-application-with-complete.html И это работало хорошо для простых классов, но сейчас я пытаюсь протестировать класс, который зависит от другого, и от другого, и т. Д.

Сначала я получил ошибку компоновщика, поэтому я добавил *.m файлы к цели теста, но теперь я получаю предупреждение для каждого класса, который я пытаюсь протестировать:

Класс Foo реализован в обоих MyApp и MyAppTestCase. Один из двух будет использоваться. Какой из них не определен.

Интересно, почему это? Как я могу решить это? Может быть, я что-то упустил при настройке цели модульного теста?

Редактировать - Решение

  • Установите "Bundle Loader" правильно на $(BUILT_PRODUCTS_DIR)/AppName.app/AppName

  • Установите для «Символы, скрытые по умолчанию» значение NO (в настройках сборки целевого приложения). Отсюда и ошибки компоновщика, потому что по умолчанию это ДА! Я так долго боролся с этим!

Источник: Ошибка связывания для модульного тестирования с XCode 4?

Ответы [ 6 ]

43 голосов
/ 27 мая 2011

Класс Foo реализован в MyApp и MyAppTestCase.Один из двух будет использован.Какой из них не определен.

Интересно, почему это так?

, потому что оба изображения (приложение и пакет модульного теста) определяют реализацию класса.класс динамически загружается в среду выполнения objc.среда выполнения objc использует плоское пространство имен.как это работает:

  • двоичный файл загружается, начиная с его зависимостей
  • при загрузке каждого двоичного файла, классы objc регистрируются во время выполнения objc
  • , есликласс с определенным именем загружается дважды, поведение не определено.одна реализация класса (с одинаковыми именами) может быть загружена в среду выполнения objc.

типичная проблема в том, что вам будет возвращена одна реализация - ваше приложение скорее всегосбой при конфликте типов (когда класс не происходит из одного и того же исходного файла).

Обычно этого можно избежать, переименовав класс или экспортировав класс в одном изображении.переименование класса, очевидно, не относится к вашему делу.у вас есть один файл Foo.m, который компилируется, экспортируется и загружается двумя изображениями, когда он должен быть в одном.

это должно быть интерпретировано вами как ошибка компоновщика дубликатов символов.несмотря на то, что реализация - это тот же исходный файл (и реализация та же) - эту проблему вы должны решить.

Как я могу решить эту проблему?

если Foo.m является классом приложения, вы должны удалить (не компилировать и не ссылаться) Foo.m из модульного теста.если это часть модульного теста, не компилируйте и не связывайте его с целью модульного теста.

затем следуйте инструкциям в посте для привязки / загрузки вашего модульного теста в приложение.это в этой общей области поста: где «WhereIsMyMac» - это имя приложения, которое вы тестируете модулем.Это позволит тестировать целевую ссылку на приложение (поэтому вы не получите ошибок компоновщика при компиляции). важная часть состоит в том, что ваши тестовые файлы скомпилированы в цели модульного теста (только), а классы вашего приложенияскомпилирован и связан с приложением.Вы не можете просто добавить их - они связываются и загружаются динамически.

Может быть, я что-то упустил при установке цели модульного теста?

Из статьи, на которую вы ссылались:

Примечание. Цель тестирования - это отдельная цель.Это означает, что вы должны быть осторожны с целевым членством.Все исходные файлы приложения должны быть добавлены только к цели приложения.Файлы тестовых кодов должны быть добавлены только к цели тестирования.

Часть, которую вы ошиблись, - это, вероятно, фазы соединения и загрузки пакета модульного тестирования.

17 голосов
/ 25 октября 2015

Если вы используете Cocoapods, вашему подфайлу нужны только зависимости в разделе для основной цели, а не цели теста.Если вы добавите дубликаты зависимостей для целей тестирования, вы получите сообщение об ошибке OP.

target 'MyProject' do
pod 'Parse'

end

target 'MyProjectTests' do

end

target 'MyProjectUITests' do

end
12 голосов
/ 15 ноября 2011

Для меня все, что мне нужно было сделать, это снять флажок, который делает класс Foo членом цели модульного теста.Он не должен быть членом обеих целей и должен выглядеть следующим образом:

Target Membership

Если изображение не видно, это скриншот целевого членства Xcode"панель.Есть две цели: одна со значком приложения «A» и именем теста.Другой объект является модульным тестом и имеет значок модульного теста:

Target Membership
[X] Foo
[ ] FooTests
3 голосов
/ 07 марта 2016

Для меня это произошло потому, что я развернул на устройстве, а затем на симуляторе, так как у меня включены NSZombies. Решением было переключиться на конфигурацию симулятора и выполнить «Продукт» -> «Очистить», затем переключиться на конфигурацию устройства и сделать то же самое. Ошибка ушла. Это связано с кэшем сборки.

2 голосов
/ 29 июля 2016

Причина в том, что вы переопределяете RUNPATH_SEARCH_PATHS настройки сборки вашей цели приложения, определенной в другой цели.

Решение:

Перейти кЦель вашего приложения и найдите RUNPATH_SEARCH_PATHS настройки сборки и используйте там $(inherited) флаг для обоих: Отладка и Выпуск

0 голосов
/ 27 августа 2018

Встречайтесь с теми же проблемами, моя ситуация в том, что Class NSNotification реализован в обоих /System/Library/Frameworks/Foundation.framework/Foundation, есть ли какие-нибудь чуваки, сталкивающиеся с той же проблемой, любые указания или советы будут оценены.1001 *

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...