Search code examples
swiftunit-testingdelegatesurlsession

Swift: Testing a URLSession called with delegates


I'm trying to do the unit tests for my app.

I've this function preparing the request

func getWeatherDataAtLocation() {
        let WEATHER_URL = "http://api.openweathermap.org/data/2.5/weather"
        let weatherAPI = valueForAPIKey(named:"weatherAPI")
        let lat = String(locationService.latitude)
        let lon = String(locationService.longitude)
        do {
        try networkService.networking(url: "\(WEATHER_URL)?APPID=\(weatherAPI)&lon=\(lon)&lat=\(lat)", requestType: "weather")
        } catch let error {
            print(error)
        }
    }

I've a service class networkservice processing the network request :

class NetworkService {

    var weatherDataDelegate: WeatherData?
    var session: URLSession

    init(session: URLSession = URLSession(configuration: .default)) {
        self.session = session
    }

    func networking(url: String, requestType: String) {

        var request = URLRequest(url: requestUrl)
        request.httpMethod = "GET"

        var task: URLSessionDataTask
        task = session.dataTask(with: request) { (data, response, error) in
            switch requestType {
            case "weather":
                do {
                    let weatherJSON = try JSONDecoder().decode(WeatherJSON.self, from: data)
                    self.weatherDataDelegate?.receiveWeatherData(weatherJSON)
                } catch let jsonErr {
                    print(jsonErr)
                }
            case // Other cases
            default:
                print("error")
            }
        }
        task.resume()
    }
}

Then i've the delegate running this function to update the JSON received

func receiveWeatherData(_ data: WeatherJSON) {
        self.dataWeather = data
        do {
            try updateWeatherDataOnScreen()
        } catch let error {
            print(error)
        }
    }

The issue is I've no idea how I can write some code to test this and all the ressources I find is to test with a callback, any idea?


Solution

  • So there are mutliple steps in this.

    1: Create a mocked version of the response of exactly this request. And save it in a json file. Named like weather.json

    2: Once you have done that you want to add an #ifdef testSchemeName when executing request. And tell it to tell your function called networking() to read from a file named "\(requestType).json" instead of making the request.

    Optional, more advanced way:

    This actually intercepts your request and send you the file data instead. A bit more advanced, but your testing gets 1 level deeper.