在 iOS 逻辑测试中使用 CocoaPods 时找不到库

我正在尝试编写一些 iOS 逻辑测试,针对项目中使用我 podspec 中某些库的功能的类。我使用的是 Xcode 中提供的标准单元测试包(尽管不是应用程序测试,只是单元测试)。

例如,我使用 Magical Record,并且在 podspec 中链接了这个库。它出现在我工作区的 Pods 项目中,当应用程序在模拟器或设备上运行时,它会按预期工作。然而,当我尝试链接到使用 Magical Record 的测试对象时,我得到一个链接器错误,说明它无法从 Magical Record 中找到选择器。我尝试在逻辑测试包中更新 HEADER _ SEARCH _ PATH,甚至将其硬编码到 CocoaPods 创建的 HEADER 目录中,但没有成功。

我可以毫无问题地对不使用 CocoaPods 库的类运行单元测试。

我说错了吗?我是否应该做一些其他的事情来让编译器查看 CocoaPods 库?

52958 次浏览

通过查看我的应用程序的主要目标是如何从 CocoaPods 库接收设置,我明白了这一点。CocoaPods 包括一个。名为 Pods.xcconfig 的 xcconfig 文件。此文件包含所有头搜索路径。

如果在项目导航器中查看项目并单击 Info 选项卡,您将看到顶部部分列出的构建配置。如果打开不同配置的披露三角形,您将看到 Pods 列在主目标下。我必须单击下拉菜单并将 Pods 添加到逻辑测试目标。

Configurations Snapshot

我还必须从主目标复制 $(inherited)${PODS_HEADERS_SEARCH_PATHS}的设置,并将它们复制到 Build Settings/HEADER _ SEARCH _ PATHS 下的逻辑测试目标。

最后,我必须在 Link Binary with Library 构建阶段为逻辑测试目标添加 libPods.a。

希望这能帮到别人。

同样值得注意的是,如果你将 libPods.a添加了两次,你将会得到一些像下面这样的严重错误:

232 duplicate symbols for architecture i386

要修复它,只需删除项目资源管理器中的一个 libPods.a引用。

我在这里找到了一个解决方案:

在 Xcode 打开项目文件,然后选择项目(而不是目标) ,在右侧面板中有一个名为“配置”的部分。为您的测试目标选择“基于配置文件”列中的 Pods。

enter image description here

CocoaPods 1.0改变了它的语法,现在看起来是这样的:

def shared_pods
pod 'SSKeychain', '~> 0.1.4'
...
end


target 'Sail' do
shared_pods
end


target 'Sail-iOS' do
shared_pods
end

Pre CocoaPods 1.0答案

你要用的是 Podfile中的 link_with,比如:

link_with 'MainTarget', 'MainTargetTests'

然后再次运行 pod install

当我在某个版本控制期间丢失了一些库文件时,也发生了类似的情况。我仍然在我的 Pods 中看到了库文件,但由于缺少实际的代码,XCode 说它不见了。令我沮丧的是,运行“ pod install”并没有立即带回丢失的文件。

我不得不手动移除并更换吊舱,具体操作如下:

  1. 把图书馆从 Podfile 移走
  2. 运行“ pod install”完全删除库
  3. 把图书馆放回 Podfile
  4. 再次运行‘ pod install’

这应该会使问题图书馆恢复到原来的形式。

我对这个问题的解决方案是修改我的 Podfile,使其在两个目标中都包含这个库,如下所示

target "MyApp" do
pod 'GRMustache', '~> 7.0.2'
end


target "MyAppTests" do
pod 'GRMustache', '~> 7.0.2'
end

由于我使用的是 Swift,因此我还必须配置测试目标以包含 MyApp-Bridging-Header.h文件。(在“生成设置”选项卡下的“迅速编译器”组中)

我同意其他的回答,即有必要将库链接到测试目标。然而,到目前为止,没有一个建议对我有帮助。正如@Fabb 在评论中所写的: “当测试时,isSubclassOfClass:调用在应该返回 YES 的地方返回 NO。我可以解释这一点的唯一原因是,依赖关系实际上与主要目标和测试目标都有联系,当测试目标的包装入器装入主要包时,它无法决定采用哪个类。”在这个帖子中,我得到了以前所有建议的相同问题。

我开始工作的解决方案是更新我的 Podfile,为我的主要目标和测试目标定义特定的 Pods:

target 'MyTarget' do
pod 'AFNetworking', '~> 2.5.0'
pod 'Mantle', '~> 1.5'
end


target 'MyTargetTests' do
pod 'OCMockito', '~> 1.3.1'
end

为我的测试目标指定一个 Pod 是 有需要,即使我没有使用任何特定于测试的 Pods。否则,CocoaPods 将不会在我的项目中插入必要的链接逻辑。

这个链接帮助我得出了这个结论。

我添加了 :exclusive => true以避免应用程序测试目标中的重复符号错误。

target 'myProjectTests', :exclusive => true do
pod 'OCMock', :head
pod 'XCTAsyncTestCase', :git => 'https://github.com/iheartradio/xctest-additions.git'
end


link_with 'myProject', 'myProjectTests'

当我将应用程序测试目标更改为逻辑单元测试目标时,将发生链接器错误。 在我删除 :exclusive => true之后,一切都会再次工作。

target 'myProjectTests', do
pod 'OCMock', :head
pod 'XCTAsyncTestCase', :git => 'https://github.com/iheartradio/xctest-additions.git'
end


link_with 'myProject', 'myProjectTests'

:exclusive => true声明 do...end之外的所有东西都不应该链接到 myProjectTests,这在应用程序测试目标中是合理的,但是它会导致逻辑测试目标中的链接器错误。

您可以根据@Keith Smiley 解决方案使用 link _ with。

如果您有通用的 pods 和每个目标的具体内容,您可能需要使用“ def”选项来定义 pods 组。并在稍后的独占目标中使用“ def”。

def import_pods
pod 'SSKeychain'
end


target 'MyProjectTests', :exclusive => true do
import_pods
end


target 'MyProject', :exclusive => true do
import_pods
pod 'Typhoon'
end

在上面的例子中,我在两个目标中都添加了“ SSKeychain”,并且只在“ MyProject”目标中添加了“ TyTaiwan”

我正在用我的 Swift 应用在 iOS 上整合 GoogleMaps Objective-C POD,所以对我来说,问题是 Test 目标在构建设置中没有参考桥头文件(桥接头)。确保您的应用程序和测试应用程序的目标都指向这一点,以便第三方 API 调用(映射 API 等)可以在快速的单元测试中使用。

从 CocoaPods 1.x 开始,有了一种新的方法来声明目标和相应测试目标之间的共享依赖关系。到目前为止,我一直在使用 Mark Struzinski 公认的解决方案,但是在运行我的测试时,使用这种方法产生了大量的警告:

Class SomeClass is implemented in both /Path/To/Test/Target and /Path/To/App/Target. One of the two will be used. Which one is undefined.

使用 CocoaPods 1.x,我们可以通过父目标的搜索路径将 our-Test 目标声明为继承,如下所示:

target 'MyApp' do
pod 'aPod'
pod 'anotherPod'
project 'MyApp.xcodeproj'
end
target 'MyAppTests' do
inherit! :search_paths
project 'MyApp.xcodeproj'
end

这将导致-Test 目标可以访问 app 目标的依赖项,而不需要多个二进制副本。这大大加快了我的测试构建时间。

下一个语法为我提供了最佳结果(在 cocoapod v. 1.2.1下进行了测试) :

Https://github.com/cocoapods/cocoapods/issues/4626#issuecomment-210402349

 target 'App' do
pod 'GoogleAnalytics' , '~> 3.0'
pod 'GoogleTagManager' , '~> 3.0'


pod 'SDWebImage', '~>3.7'
platform :ios, '8.0'
use_frameworks!


target 'App Unit Tests' do
inherit! :search_paths
end
end

没有这个我有警告,而测试运行关于重复符号。

在这些警告消失之后。

试试这个对我有用,

我们需要设置豆荚的配置,

Xcode 项目(您的项目)中的 Project-> Info-> Configurations 应该设置为主项目“ Pods”,用于调试、发布(以及其他内容)。请参阅“ Header not found-search path not include”“标题未找到-搜索路径未包含”

enter image description here

希望这对某人有所帮助。

我在 XCTest 下使用 OpenCV 时遇到了问题。对于像 cv::Mat这样的类,它给了我 Undefined symbols for architecture arm64的连接器错误。我正在使用主目标下的 pod 'OpenCV', '~> 2.0'通过 CocoaPods 安装 OpenCV。无论我多么努力地尝试将 OpenCV 依赖项置于测试目标之下,或者使用 inherit! :search_paths,它们都不起作用。解决方案是创建一个像这样的 abstract_target:

# Uncomment the next line to define a global platform for your project
platform :ios, '6.1.6'


abstract_target 'Shows' do
pod 'RMVision', path: '../..'
pod 'RMShared', path: '../../../RMShared'
pod 'OpenCV', '~> 2.0'


target 'RMVisionSample' do
# Uncomment the next line if you're using Swift or would like to use dynamic frameworks
# use_frameworks!


# Pods for RMVisionSample
end


target 'RMVisionSampleTests' do
# inherit! :search_paths
# Pods for testing
end


target 'RMVisionBenchmarks' do
# inherit! :search_paths
# Pods for testing
end


end


同样有用的是 pod deintegratepod clean命令,它们有助于清理项目,并确保您在测试时重新开始。您可以使用 [sudo] gem install cocoapods-deintegrate cocoapods-clean安装这两个程序。