Inserting PHAsset in XCTest setup

I'd like to test some code that uses image and video assets.


I'd like to insert sample assets in the setUp phase of my XCTest but find that this fails with NSCocoaErrorDomain Code=-1 "The operation couldn’t be completed. (Cocoa error -1.)


video1.m4v is a member both of the main app target, and of the test target so I should be accessible.


First tried with the older ALAssetsLibrary approach. The code works in the main app (without the expectations) but not in the test runner.


- (void)setUp {
    [super setUp];
    NSURL *path =  [[NSBundle mainBundle] URLForResource:@"video1"  withExtension:@"m4v" ];
   XCTestExpectation *exp = [self expectationWithDescription:@"video"];
    [self.assetsLibrary writeVideoAtPathToSavedPhotosAlbum:path completionBlock:(ALAssetsLibraryWriteVideoCompletionBlock) ^{
        NSLog(@"Wrote video %@", path);
        [exp fulfill];
    }];
    [self waitForExpectationsWithTimeout:10 handler:^(NSError *error) {
        NSLog(@"Errr %@", error);
    }];
}


I've also tried the newer PhotoKit version.


-(void) setUp {
   [super setUp];

    NSBundle *bundle = [NSBundle bundleForClass:[self class]];
    self.pathURL =  [bundle URLForResource:@"video1"  withExtension:@"m4v" ];

   [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{   
        PHAssetChangeRequest *createAssetRequest = [PHAssetChangeRequest creationRequestForAssetFromVideoAtFileURL:self.pathURL];
        PHObjectPlaceholder *assetPlaceholder = [createAssetRequest placeholderForCreatedAsset];
        self.assetId = assetPlaceholder.localIdentifier;
    } completionHandler:^(BOOL success, NSError *error) {
        NSLog(@"Finished adding asset. %@", (success ? @"Success" : error));
    }];
]


And also setting this up with an Async approach


   XCTestExpectation *exp =  [self expectationWithDescription:@"video"];

    NSBundle *bundle = [NSBundle bundleForClass:[self class]];
    self.pathURL =  [bundle URLForResource:@"video1"  withExtension:@"m4v" ];

    [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
        PHAssetChangeRequest *createAssetRequest = [PHAssetChangeRequest creationRequestForAssetFromVideoAtFileURL:self.pathURL];
       PHObjectPlaceholder *assetPlaceholder = [createAssetRequest placeholderForCreatedAsset];
        NSLog(@"%@", assetPlaceholder.localIdentifier);
        self.assetId = assetPlaceholder.localIdentifier;

    } completionHandler:^(BOOL success, NSError *error) {
        NSLog(@"Finished adding asset. %@", (success ? @"Success" : error));
        [exp fulfill];
    }];

    [self waitForExpectationsWithTimeout:30 handler:^(NSError *error) {
        NSLog(@"%@", error.localizedDescription);
    }];


Neither works, I get a value for the localIdentifier from the assetPlaceholder but the completion handler fails each time.


The PhotoKit code is not working in the main app either though.

What's the error you get in the completion handler? I'd say the fact that your main app is also failing is probably relevant.


That being said, I really wish PhotoKit were more testable - I've been working on a "mocked" version of the entire PhotoKit library so that you can quickly set up a fake photo library to run tests against (rather than, for example, trying to set up your simulator with the right assets and then running your tests on the simulator). Right now my mock is way too hacky and dirty to release to other people, but maybe if there's demand I could spend some time polishing it and make it available for others.

Inserting PHAsset in XCTest setup
 
 
Q