简体   繁体   English

在viewDidLoad之后未在测试中设置XCTest单元测试数据响应

[英]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. 我正在尝试编写单元测试,当前正在尝试测试在viewDidLoad()接收到数据的viewController,该数据是在alamofire请求之后设置的。 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. 问题是,在我的测试函数中,当我检查成功请求后应以10个元素填充的数组时,其值为0。我检查了测试中的viewDidLoad()是否未执行,但应该执行,因为当我只是将元素添加到请求之外的另一个数组中时,特定的测试有效。 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的viewDidLoad()):

ViewController simplified : ViewController 简化了

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: ViewControllerTests类:

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 . 在iOS上,可以使用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 ) (在GitHub上有一个不错的框架可以在Swift中做到这一点: OHHTTPStubs

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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