访问 OCUnit 测试目标中的 UIImage
Posted
技术标签:
【中文标题】访问 OCUnit 测试目标中的 UIImage【英文标题】:Accessing a UIImage inside a OCUnit test target 【发布时间】:2011-12-22 10:59:50 【问题描述】:我目前正在为 iPad 应用程序编写图像处理测试。我的单元测试目标中有一个资源文件夹,里面有一张照片,但是当我尝试使用 [UIImage imageNamed:@"photo1.jpg"] 访问它时,没有返回图像。如果我将文件名更改为主资源文件夹中的一个,则会返回图像。
有没有办法访问单元测试目标中的 Resources 文件夹?
【问题讨论】:
【参考方案1】:找到了这个问题的答案,貌似不能用[UIImage imageNamed:],可以这样访问图片:
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
NSString *imagePath = [bundle pathForResource:@"photo1" ofType:@"jpg"];
UIImage *image = [UIImage imageWithContentsOfFile:imagePath];
【讨论】:
【参考方案2】:从 ios 8 开始,我们有:-imageNamed:inBundle:compatibleWithTraitCollection:
UIImage
上的失败初始化
在 Swift 中:
let bundle = NSBundle(forClass: self.dynamicType)
let image:UIImage? = UIImage(named: "imageFileName",
inBundle:bundle,
compatibleWithTraitCollection:nil)
在 Objective-C 中
NSBundle* bundle = [NSBundle bundleForClass:[self class]];
UIImage* image = [UIImage imageNamed:@"imageFileName.extension"
inBundle:bundle
compatibleWithTraitCollection:nil];
Documentation
【讨论】:
这个答案应该在顶部。我已经为 UIImage 创建了一个新的初始化程序来完成它已经完成的工作。我现在感觉有点傻。 gist.github.com/Psidium/6d15525d4fba7b191290【参考方案3】:为此做了一个方便的分类。
image = [UIImage testImageNamed:@"image.png"];
类似:
@interface BundleLocator : NSObject
@end
@interface UIImage (Test)
+(UIImage*)testImageNamed:(NSString*) imageName;
@end
@implementation BundleLocator
@end
@implementation UIImage (Test)
+(UIImage*)testImageNamed:(NSString*) imageName
NSBundle *bundle = [NSBundle bundleForClass:[BundleLocator class]];
NSString *imagePath = [bundle pathForResource:imageName.stringByDeletingPathExtension ofType:imageName.pathExtension];
return [UIImage imageWithContentsOfFile:imagePath];
@end
【讨论】:
【参考方案4】:您可以使用以下类别(但仅将其添加到测试目标!)。它将使 UIImage imageNamed: 方法在测试目标中自动工作:
.h 文件
/**
* UIImage imageNamed: method does not work in unit test
* This category provides workaround that works just like imageNamed method from UIImage class.
* Works only for png files. If you need other extension, use imageNamed:extension: method.
* NOTE: Do not load this category or use methods defined in it in targets other than unit tests
* as it will replace original imageNamed: method from UIImage class!
*/
@interface UIImage (ImageNamedForTests)
/**
* Returns image with the specified name and extension.
* @param imageName Name of the image file. Should not contain extension.
* NOTE: You do not have to specify '@2x' in the filename for retina files - it is done automatically.
* @param extension Extension for the image file. Should not contain dot.
* @return UIImage instance or nil if the image with specified name and extension can not be found.
*/
+ (UIImage *)imageNamed:(NSString *)imageName extension:(NSString *)extension;
@end
.m 文件
#import "UIImage+ImageNamedForTests.h"
#import <objc/runtime.h>
@implementation UIImage (ImageNamedForTests)
+ (void)load
[self swizzleClassMethod];
+ (void)swizzleClassMethod
SEL originalSelector = @selector(imageNamed:);
SEL newSelector = @selector(swizzled_imageNamed:);
Method origMethod = class_getClassMethod([UIImage class], originalSelector);
Method newMethod = class_getClassMethod([UIImage class], newSelector);
Class class = object_getClass([UIImage class]);
if (class_addMethod(class, originalSelector, method_getImplementation(newMethod), method_getTypeEncoding(newMethod)))
class_replaceMethod(class, newSelector, method_getImplementation(origMethod), method_getTypeEncoding(origMethod));
else
method_exchangeImplementations(origMethod, newMethod);
+ (UIImage *)swizzled_imageNamed:(NSString *)imageName
return [self imageNamed:imageName extension:@"png"];
+ (UIImage *)imageNamed:(NSString *)imageName extension:(NSString *)extension
NSBundle *bundle = [NSBundle bundleForClass:[SomeClassFromUnitTestTarget class]];//Any class from test bundle can be used. NOTE: Do not use UIImage, as it is from different bundle
NSString *imagePath = [bundle pathForResource:imageName ofType:extension];
return [UIImage imageWithContentsOfFile:imagePath];
【讨论】:
以上是关于访问 OCUnit 测试目标中的 UIImage的主要内容,如果未能解决你的问题,请参考以下文章
UINavigationController 中的 OCUnit 测试问题
为 iOS 构建 OCUnit 应用程序测试目标时出现链接器错误
如何在单元测试(OCUnit)中访问 NSDocumentDirectory