【问题标题】:Accessing a UIImage inside a OCUnit test target访问 OCUnit 测试目标中的 UIImage
【发布时间】:2011-12-22 10:59:50
【问题描述】:

我目前正在为 iPad 应用程序编写图像处理测试。我的单元测试目标中有一个资源文件夹,里面有一张照片,但是当我尝试使用 [UIImage imageNamed:@"photo1.jpg"] 访问它时,没有返回图像。如果我将文件名更改为主资源文件夹中的一个,则会返回图像。

有没有办法访问单元测试目标中的 Resources 文件夹?

【问题讨论】:

    标签: iphone objective-c ipad unit-testing ocunit


    【解决方案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

      【讨论】:

      【解决方案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];
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-11-22
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多