How to test services that make async network calls in Swift and return an Optional
One of the things that threw me the first time I did iOS development was the fact network calls were done asynchronously by default. From an implementation side this was nice, I didn’t have to worry about blocking my main thread. But from a testing side… well that was something new.
Since then Apple’s come out with Swift. And with Swift comes the need to learn new ways to do things. A couple of things I wanted to work out how to do nicely was: how can I stub out my network layer as I don’t want my test to have to run against a dummy backend, and secondly how can I assert the Optional value I get back is set.
Turns out it wasn’t too tricky. The optional var was set as a result of an async call, so the easiest way to check the value is to first wait till the var has a non nil value.
And stubbing out the network layer was easily achieved by using OHHTTPStubs.
My final test ended up looking like:
func testSubmitsAndProcessesResultFromRemoteService() { let service = CoinEntryService() let expectedResponse: JSON = ["amountEnteredSoFar":NSDecimalNumber(double: 2.50), "enoughFundsEntered":false] stub(isHost("localhost")) { _ in return OHHTTPStubsResponse(JSONObject: expectedResponse.rawValue, statusCode: 200, headers: nil) } var coinEnteredResult: CoinEnteredResult? service.coinEntered(NSDecimalNumber.one()) { result in coinEnteredResult = result } expect(coinEnteredResult).toEventuallyNot(beNil()) expect(coinEnteredResult?.amountEnteredSoFar).to(equal(NSDecimalNumber(double: 2.5))) }