简体   繁体   中英

XCTest Unit Test data response not set in test after viewDidLoad

I'm trying to write Unit Tests and currently I try to test a viewController which received data in viewDidLoad() , the data is set after a alamofire request. The problem is, that in my test function when I check the array which should be filled with 10 elements after the successful request, is 0. I've checked if viewDidLoad() in the test is not executed, but it should be, because when I just add elements to another array, which is outside the request, the specific test works. I guess, it has something to do with the request and I didn't found answer so far.

Here is the code (this question with explanation , helped me to execute the viewDidLoad() of the viewController):

ViewController simplified :

class ViewController: UIViewController {

  var itemsFromRequest: [Int] = []
  var itemsWithoutRequest: [Int] = []

  override func viewDidLoad() {
    super.viewDidLoad()

    // array with 10 elements
    itemsWithoutRequest = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

    Alamofire.request(url: URLConvertible).responseJSON { response in
      //...error handling, parsing etc.

      // set array after successful response
      self.itemsFromRequest = responseData
    }
  }
}

The ViewControllerTests class:

class ViewControllerTests: XCTestCase {

  var viewController: ViewController!

  override func setUp() {
    super.setUp()

    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    viewController = storyboard.instantiateViewController(withIdentifier: "ViewController") as! ViewController
    // trigger viewDidLoad() of viewController
    let _ = viewController.view
  }

  func testItemArraysHaveTenItems() {
    // This is successful
    XCTAssertEqual(viewController.itemsWithoutRequest.count, 10)
    // This failed with error "XCTAssertEqual failed: ("0") is not equal to ("10")"
    XCTAssertEqual(viewController.itemsFromRequest.count, 10)
  }
}

Why does the second Assertion failed?

Problem

On the second Assertion you expect data which are loaded asynchronously, but you check them synchronously and at the time you are checking for them, the network operation has not finished yet, so of course it is going to fail.

Solution

Testing asynchronously is available on iOS using XCTestExpectation .

Example of use

let testExpectation = expectation(description: "Asynchronous expectation")
let sut = SubjectUnderTest()

sut.executeAsynchronousOperation(completion: { (error, data) in
    XCTAssertTrue(error == nil)
    XCTAssertTrue(data != nil)

    testExpectation.fulfill()
})

waitForExpectations(timeout: 5, handler: .none)

Tips

Another thing to point out is that testing network operations and waiting for the response is a bad practice, you should intercept the network requests and return local data instead of waiting for the real data from the server. (On GitHub there is a nice framework to do that in Swift: OHHTTPStubs )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM