Force Alamofire to do everything on main thread?

315 Views Asked by At

Is there a way to force Alamofire to do all of its work on the main thread? This is for a test scenario where I need the main thread to not continue execution until the network calls have completed and I know the status. The tests in question used to run under the XCTest framework and so I would use XCTestExpectation to wait for completion. The environment I'm using doesn't work with XCTest and so I need Alamofire to be synchronous.


Since the first 2 comments have both suggested how I should test, let me provide a little more context.

I have about 100 tests that have been running just fine for the last 2 years. The tests are NOT unit tests but UI Tests using Google's EarlGrey 1. EarlGrey 1 provides UI testing that runs under XCTest so you can combine UI Testing with white box inspection of the app state. It's great.

Earl Grey 1 does not support iOS 13 and so I am porting the tests to EarlGrey 2, which runs on top of XCUITest. For the white box aspect, you make remote calls from the test process to a bundle that is injected into your app.

In this case the "mock" is the server, but it does make network calls and these happen when I call into the test bundle. I need to know when they finish so I can return after they're done.

1

There are 1 best solutions below

4
Kevin R On

To answer your question: there's no proper way to enforce Alamofire to do calls on the main thread using Alamorefire itself. Generally speaking, you can make a thread wait for a result using a Semaphore. Alamofire seems to respond on the main thread, so that would likely result in a deadlock.

You could make the thread sleep until the callback has been handled:

var result: Data?
var done = false

// Do a call which will finish asynchonously
someCall(withBlock: { someResult in
    // Once done,
    result = someResult
    done = true
})

// Make the main thread wait
while(!done) {
    Thread.sleep(forTimeInterval: 0.1)
}

// This will be called after the block has been completed
print("\(result)")

The same can be applied to Alamofire calls, do note this can create deadlocks with threads waiting on each other.

But to help you with your problem. Ideally you do not wait to perform network calls in tests for a number of reasons, including:

  • Tests should only cover a single piece of functionality, network calls go beyond that.
  • Including network calls means external factors such as no internet connection will influence the test outcome, although it says little about your code performing as expected.

A common approach is to 'mock out' parts that should be considered out-of-scope for the test. Here's a post about doing this for Alamofire.