Leverage method swizzling to test network calls

Method swizzling is a technique used in Swift and Objective-C to modify or exchange the implementations of methods at runtime. It’s a powerful and flexible technique, but it should be used with caution because it can lead to unexpected behavior and hard-to-maintain code if not used carefully. We can actually leverage this mock network calls and use it to tests.

For e.x. let’s consider you are trying to download a set of names. /v1/department/history/names

Hit this api and download all data into a JSON. You can name it as v1_department_history_names.json

Store this in the resources bundle of your app.

Lets assume the name of your method to call this API is startNetworkDownload(path: String)

e.g. startNetworkDownload(path: "/v1/department/history/names")

Basically in your code, when you run the tests, you can swizzle the network call, and read the data from the json and return directly. This will save you time and help you test network calls.

import ObjectiveC

extension UIViewController {
    @objc static func swizzleStartNetworkDownload() {
        let originalSelector = #selector(startNetworkDownload)
        let swizzledSelector = #selector(swizzledStartNetworkDownload)
        
        let originalMethod = class_getInstanceMethod(self, originalSelector)
        let swizzledMethod = class_getInstanceMethod(self, swizzledSelector)
        
        method_exchangeImplementations(originalMethod!, swizzledMethod!)
    }
    
    @objc func swizzledStartNetworkDownload:(NSString*) path {
        // Your custom implementation here
NSString *fileName = [path stringByReplacingOccurrencesOfString:@"/" withString:@"_"];
        readJSONFromFile(fileName)
    }
}

+ (id)readJSONFromFile:(NSString *)fileName {
    // Get the file path for the JSON file in the app bundle
    NSString *filePath = [[NSBundle mainBundle] pathForResource:fileName ofType:@"json"];
    
    if (!filePath) {
        NSLog(@"JSON file not found.");
        return nil;
    }
    
    // Read JSON data from the file
    NSData *jsonData = [NSData dataWithContentsOfFile:filePath];
    
    if (!jsonData) {
        NSLog(@"Failed to read JSON data from file.");
        return nil;
    }
    
    NSError *error = nil;
    
    // Parse the JSON data into a Foundation object (NSArray, NSDictionary, etc.)
    id jsonObject = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:&error];
    
    if (error) {
        NSLog(@"Error parsing JSON data: %@", error.localizedDescription);
        return nil;
    }
    
    return jsonObject;
}

Leave a Reply

Your email address will not be published. Required fields are marked *