Load files in xcode unit tests
Solution 1
When running tests the application bundle is still the main bundle. You need to use unit tests bundle.
Objective C:
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
NSString *path = [bundle pathForResource:@"TestData" ofType:@"xml"];
NSData *xmlData = [NSData dataWithContentsOfFile:path];
Swift 2:
let bundle = NSBundle(forClass: self.dynamicType)
let path = bundle.pathForResource("TestData", ofType: "xml")!
let xmlData = NSData(contentsOfFile: path)
Swift 3 and up:
let bundle = Bundle(for: type(of: self))
let path = bundle.path(forResource: "TestData", ofType: "xml")!
let xmlData = NSData(contentsOfFile: path)
Solution 2
With swift Swift 3 the syntax self.dynamicType
has been deprecated, use this instead
let testBundle = Bundle(for: type(of: self))
guard let ressourceURL = testBundle.url(forResource: "TestData", ofType: "xml") else {
// file does not exist
return
}
do {
let ressourceData = try Data(contentsOf: ressourceURL)
} catch let error {
// some error occurred when reading the file
}
or
guard let ressourceURL = testBundle.url(forResource: "TestData", withExtension: "xml")
Solution 3
As stated in this answer:
When the unit test harness runs your code, your unit test bundle is NOT the main bundle. Even though you are running tests, not your application, your application bundle is still the main bundle.
If you use following code, then your code will search the bundle that your unit test class is in, and everything will be fine.
Objective C:
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
NSString *path = [bundle pathForResource:@"TestData" ofType:@"xml"];
NSData *xmlData = [NSData dataWithContentsOfFile:path];
Swift:
let bundle = NSBundle(forClass: self.dynamicType)
if let path = bundle.pathForResource("TestData", ofType: "xml")
{
let xmlData = NSData(contentsOfFile: path)
}
Solution 4
Relative paths are relative to the current working directory. By default, that's / — the root directory. It's looking for that folder at the root level of your startup disk.
The correct way to get a resource that's within your bundle is to ask your bundle for it.
In an application, you'd get the bundle using [NSBundle mainBundle]
. I don't know if that works in a test case; try it, and if it doesn't (if it returns nil
or an unuseful bundle object), substitute [NSBundle bundleForClass:[self class]]
.
Either way, once you have the bundle, you can ask it for the path or URL for a resource. You generally should go for URLs unless you have a very specific reason to need a path (like passing it to a command-line tool using NSTask). Send the bundle a URLForResource:withExtension:
message to get the resource's URL.
Then, for the purpose of reading a string from it, use [NSString stringWithContentsOfURL:encoding:error:]
, passing the URL you got from the bundle.
Solution 5
Get main bundle
Use main bundle to get local mock data
Load data from JSON
let mainBundle = Bundle(identifier: "com.mainBundle.Identifier") if let path = mainBundle?.path(forResource: "mockData", ofType: "json") { do { let testData = try Data(contentsOf: URL(fileURLWithPath: path)) networkTestSession.data = testData } catch { debugPrint("local json test data missing") } }
ArdenDev
Updated on July 05, 2022Comments
-
ArdenDev almost 2 years
I have an Xcode 5 unit test project and some test xml files related to it. I've tried a bunch of approaches but I can't seem to load the xml files.
I've tried the following which does not work
NSData* nsData = [NSData dataWithContentsOfFile:@"TestResource/TestData.xml"]; NSString* fileString = [NSString stringWithContentsOfFile:@"TestData.xml" encoding:NSUTF8StringEncoding error:&error];
Also if I try to preview all the bundles using [NSBundle allBundles] the unit test bundle does not appear in the list?
I tried to create a separate resource bundle and I can't seem to locate it programmatically although it does get built and deployed.
What am I doing wrong ?
-
ArdenDev over 10 yearsSo I found out that loading the bundle using its identifier worked. Although this identifier is not part of the array in [NSBundle allBundles]. Ideally it should list it ...
-
colbadhombre almost 9 yearsIn the Swift example, I think you mean to have "bundle" instead of "testBundle" on the second line.
-
mac10688 over 8 yearsThis answer is basically the same as the one provided a year before it.
-
mac10688 over 8 years@stevo.mit My apologies!
-
Mitchell Currie over 7 yearsWell kept up to date
-
Luke Rogers almost 6 yearsThis shows better practice Swift than the most popular answer: no force unwraps, preferring URLs over paths, and using
Data
rather thanNSData
. -
abhimuralidharan over 5 years
[self class]
was the fix.[NSBundle MainBundle]
will not work here. This solved my issue. Thanks man.