How do I unit-test logic involving CLBeacons?

core-location, ibeacon, ios, unit-testing

Solution

I have done this by using OCMockito with XCTest.

CLBeacon *mockBeacon = mock([CLBeacon class]);

Then I can use this to call the delegate methods on the class that is the CoreLocation delegate. The test might look like this:

- (void)testDidRangeOnABeacon
{
    MyLocationDelegate *myDelegate = [[MyLocationDelegate alloc] init];

    CLLocationManager *mockManager = mock([CLLocationManager class]);
    CLBeacon *mockBeacon  = mock([CLBeacon class]);
    CLBeaconRegion *mockRegion  = mock([CLBeaconRegion class]);


    [myDelegate locationManager:mockManager
                didRangeBeacons:@[mockBeacon]
                       inRegion:mockRegion];


    // XCTAsserts...
    XCTAssert([myDelegate.checkSomethingAboutRanging]);
}

Problem

I'd like to run some tests on a view controller involving CLBeacons. Unfortunately, while CLBeacons are not themselves a private class, all the necessary properties on them are read-only, without any write accessors. The methods are written in a manner that should help maximize testability, but without the ability to generate the CLBeacons, how do I test my view controller's logic regarding them? Edit: To explain the scope of my purpose, I'm experiencing some odd behavior in the app at times. I want to try and confirm the source of the odd behavior is in a specific area of code by testing various scenarios and confirming that various other related components in my code work correctly. (E. g. I can test that my data handling works correctly, therefore I'll know it's the animation / layout code that is misbehaving).

Original source