23

I can't get XCTestCase unit tests for a Cocoa Touch Static Library which rely on code that uses imageNamed to work.

I added my image "plane.png" to the test target, but [UIImage imageNamed] keeps returning nil.
When I explicitly specify the path of the image in the test and load the image from file it does work.

NSString* imagePath = [[[NSBundle bundleForClass:[self class]] resourcePath] stringByAppendingPathComponent:@"plane.png"];
UIImage* imageWorks = [UIImage imageWithContentsOfFile:imagePath];

UIImage* imageStaysNil = [UIImage imageNamed:@"plane.png"];

How can I write unit tests for code that uses imageNamed?

Pieter
  • 17,435
  • 8
  • 50
  • 89

3 Answers3

24

In XCTest you aren't in mainBundle. So get your image from your XCTest bundle.

(this solution is for iOS8+)

ObjC

[UIImage imageNamed:@"..." inBundle:[NSBundle bundleForClass:[self class]] compatibleWithTraitCollection:nil];

Swift

UIImage(named: "...", in: Bundle(for: type(of: self)), compatibleWith: nil)
Community
  • 1
  • 1
Cœur
  • 37,241
  • 25
  • 195
  • 267
  • This new function does use the system image cache, unlike `imageWithContentsOfFile`, so in iOS8+ it's possible to test. Having to change all `imageNamed` calls simply to be able to unit test the code is not ideal though, but it'll do. – Pieter Jun 08 '16 at 07:35
  • @Fonix in swift 4.0, 4.1 and 4.2, `type(of: self)` works fine, no need to change it. – Cœur Aug 30 '18 at 10:34
  • @Cœur you are right, it does work, im not sure what i did earlier but it was giving me a compile error and coincidentally changing the `type(of: self)` got it to work for me so i just assumed it was that, maybe was just xcodes error warnings not updating in a timely fashion – Fonix Aug 30 '18 at 11:34
2

The accepted answer didn't work for me; here's what did.

let image = UIImage(contentsOfFile: 
    Bundle(for: type(of: self))
    .path(forResource: "plane", ofType: "png")!)!
ratbum
  • 1,030
  • 12
  • 29
1

Since your xctest project acts like different project It's mandatory to add your .png file for xctest also.

add your plane.png image to xctest project also. Make sure you have checked like

enter image description here

It works fine for me with the same code

enter image description here

Rajesh
  • 10,318
  • 16
  • 44
  • 64
  • The image is added to the test target (I don't think the loading from file would work if it weren't?) – Pieter Apr 07 '14 at 07:56
  • It doesn't work for me, I'm testing a "cocoa touch static library", so the resource can't be added to the static library itself, maybe that's the difference? – Pieter Apr 07 '14 at 08:08
  • is your image added to static library? – Rajesh Apr 07 '14 at 08:09
  • No, you can't really add resources to a static library, see https://developer.apple.com/library/ios/technotes/iOSStaticLibraries/Articles/creating.html – Pieter Apr 07 '14 at 08:10
  • I created a new application project, and there it does indeed work, but not for a static library. Clarified the question, thanks for helping me narrow the problem down – Pieter Apr 07 '14 at 08:12
  • I know that you can't include the image or any other resources in static library. But you can have them in library project. When you dragging your library you should add your image/Resource/Asset to the main project. In that sense i asked – Rajesh Apr 07 '14 at 08:13
  • Well, you can't, really, try it. You can check the box when you add the file and if you then inspect your file it will no longer be checked for the library itself but only for the test target. – Pieter Apr 07 '14 at 08:15