Fixture data for iOS tests

Jonah Williams ·

I have talked about running xcode units tests from the command line before. When I’m running tests I often want to load some sort of test fixture data for use in my tests. For example: I might want to keep a file of recorded API responses so that I can stub out network calls.

In an application I would normally load a local resource using NSBundle:

NSBundle *bundle = [NSBundle mainBundle];
NSDictionary *data = [NSDictionary dictionaryWithContentsOfURL:[bundle URLForResource:@"data" withExtension:@"plist"]];

However this won’t work for resources included only in a logic test target. Instead I have to find the test class’ bundle:

- (void)testLoadingResources
{
    NSBundle *bundle = [NSBundle bundleForClass:[self class]];
    NSDictionary *data = [NSDictionary dictionaryWithContentsOfURL:[bundle URLForResource:@"test_data" withExtension:@"plist"]];

Breaking into the debugger while running tests we can see that multiple bundles are available when running logic tests (when a TEST_HOST has not been set):

(lldb) po [NSBundle allBundles]
(id) $4 = 0x01939c90 <__NSArrayI 0x1939c90>(
NSBundle </Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator5.1.sdk/Developer/usr/bin> (loaded),
NSBundle </Users/Jonah/Library/Developer/Xcode/DerivedData/demo-cmievackjxrgicduqyniuhyntvje/Build/Products/Debug-iphonesimulator/demoTests.octest> (loaded)
)

While application tests only have a single bundle:

(lldb) po [NSBundle allBundles]
(id) $3 = 0x06a527f0 <__NSArrayI 0x6a527f0>(
NSBundle </Users/Jonah/Library/Application Support/iPhone Simulator/5.1/Applications/E4292AB1-4F69-4D7D-AF96-C9FA09B34F17/demo.app> (loaded)
)

[NSBundle bundleForClass:[self class]] will return the appropriate bundle in either case.