Search code examples
swiftxcodecocoapodsalamofirexcode-ui-testing

Unable to use Alamofire in an xcode UI Test with Swift


The issue I am having is getting Alamofire to work with the xcode UI Testing.

I have isolated the parts down as much as I can to try and identify where the issue might be, but still can't solve this one. With a new xcode project using swift, I can use Alamofire as expected with the main ViewController.swift and the func viewDidLoad() function okay, but when creating a UI Test, I am unable to use the same code in the func testExample() function.

Versions of tools used:

Xcode     = 9.2(9C40b)    
Swift     = 4.0
cocoapods = 1.4.0     
macOS     = High Sierra Version 10.13.2 (17C205)  
Alamofire = 4.5    

ViewController.swift - Working okay

import UIKit
import Alamofire

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        Alamofire.request("https://httpbin.org/get").responseJSON { response in
            print("Request: \(String(describing: response.request))")   // original url request
            print("Response: \(String(describing: response.response))") // http url response
            print("Result: \(response.result)")                         // response serialization result

            if let json = response.result.value {
                print("JSON: \(json)") // serialized json response
            }

            if let data = response.data, let utf8Text = String(data: data, encoding: .utf8) {
                print("Data: \(utf8Text)") // original server data as UTF8 string
            }

        }


    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

Result

Request: Optional(https://httpbin.org/get) Response: Optional( { URL: https://httpbin.org/get } { Status Code: 200, Headers { "Access-Control-Allow-Credentials" = ( true etc...

UITestExample() - Not Working

//
//  exalamUITests.swift
//  exalamUITests
//


import XCTest
import Alamofire

class exalamUITests: XCTestCase {

    override func setUp() {
        super.setUp()

        // Put setup code here. This method is called before the invocation of each test method in the class.

        // In UI tests it is usually best to stop immediately when a failure occurs.
        continueAfterFailure = false
        // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.
        XCUIApplication().launch()

    // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp     method is a good place to do this.
    }

    override func tearDown() {
        // Put teardown code here. This method is called after the invocation of each test method in the class.
        super.tearDown()
    }

    func testExample() {
        Alamofire.request("https://httpbin.org/get").responseJSON { response in
            print("Request: \(String(describing: response.request))")   // original url request
            print("Response: \(String(describing: response.response))") // http url response
            print("Result: \(response.result)")                         // response serialization result

            if let json = response.result.value {
                print("JSON: \(json)") // serialized json response
            }

            if let data = response.data, let utf8Text = String(data: data, encoding: .utf8) {
                print("Data: \(utf8Text)") // original server data as UTF8 string
            }

        }
    }

}

Result

2018-01-29 14:55:25.974425+1000 exalamUITests-Runner[12450:454722] +[CATransaction synchronize] called within transaction
2018-01-29 14:55:26.022366+1000 exalamUITests-Runner[12450:454722] Running tests...
2018-01-29 14:55:29.229531+1000 exalamUITests-Runner[12450:454722] Continuing to run tests in the background with task ID 1
Test Suite 'Selected tests' started at 2018-01-29 14:55:29.896
Test Suite 'exalamUITests.xctest' started at 2018-01-29 14:55:29.900
Test Suite 'exalamUITests' started at 2018-01-29 14:55:29.902
Test Case '-[exalamUITests.exalamUITests testExample]' started.
    t =     0.00s Start Test at 2018-01-29 14:55:29.908
    t =     0.17s Set Up
    t =     0.18s     Open Company.exalam
    t =     0.28s         Launch Company.exalam
    t =     6.39s             Wait for Company.exalam to idle
    t =     9.13s Tear Down
Test Case '-[exalamUITests.exalamUITests testExample]' passed (9.339 seconds).
Test Suite 'exalamUITests' passed at 2018-01-29 14:55:39.244.
     Executed 1 test, with 0 failures (0 unexpected) in 9.339 (9.342) seconds
Test Suite 'exalamUITests.xctest' passed at 2018-01-29 14:55:39.245.
     Executed 1 test, with 0 failures (0 unexpected) in 9.339 (9.346) seconds
Test Suite 'Selected tests' passed at 2018-01-29 14:55:39.249.
     Executed 1 test, with 0 failures (0 unexpected) in 9.339 (9.353) seconds


Test session log:
/var/folders/ys/9lh0sqdd62s03g_d10zs46z00000gn/T/com.apple.dt.XCTest/IDETestRunSession-8C0D5A43-AB22-47EA-88C7-6AB878853EBF/    exalamUITests-9DA87773-7D75-4A9A-8127-BAE3CAB18354/Session-exalamUITests-2018-01-29_145508-bLBnaC.log

Podfile

# Uncomment the next line to define a global platform for your project
platform :ios, '9.0'

target 'exalam' do
  # Comment the next line if you're not using Swift and don't want to use dynamic frameworks
  use_frameworks!
  pod 'Alamofire', '~> 4.5'

  # Pods for exalam

  target 'exalamTests' do
    inherit! :search_paths
    # Pods for testing
  end

  target 'exalamUITests' do
    inherit! :search_paths
    use_frameworks!
    pod 'Alamofire', '~> 4.5'
    # Pods for testing
  end

end

This Question was similar, but it is over a year old and I thought I could add more detail.

I'm new to Mac, swift, xcode, and cocoapods, but I have tried all similar S.O. related answers already and tried many different things. (Usually work in python and linux)

Any help would be very much appreciated.


Solution

  • Networking in Alamofire (as all other iOS networking libraries) is asynchronous. Your test is ending well before the request is even processed by the server. That's why your closure for responseJSON method is never fired. You have to use expectations to get it work: https://developer.apple.com/documentation/xctest/asynchronous_tests_and_expectations/testing_asynchronous_operations_with_expectations

    I'm curious though, why do you need networking inside the UI test?