使用信号量的 XCTest 单异步设置

XCTest Single Asynchronous SetUp With Semaphores

我正在通过 Alamofire 测试 API。我需要对服务器进行一次调用以准备集成测试。一旦完成,我就可以开始 运行ning 测试了。

通常的override setUp()每次测试都是运行,所以我不想那样做。

因此,我选择覆盖 class setUp(),如下所述:https://developer.apple.com/reference/xctest/xctestcase

这很好,但是现在,我不能再使用标准了waitForExpectations。 (在 class override setUp()) 中,我收到几个编译器错误,告诉我我不再调用相同的 waitForExpectations 因为我在 class 方法中,而不是测试用例。

为了解决这个问题,我想像这样使用信号量:

class ServiceLayerTests: XCTestCase {
    static var apiService: APIService = APIService()
    let sessionManager = SessionManager(serverTrustPolicyManager: ServerTrustPolicyManager(policies: ["http://localhost:3000/": .disableEvaluation]))
    static var companyManger: UserWebResource?
    static var companyManagerID = -1
    override class func setUp() {
        apiService.baseURL = "http://localhost:3000/"
        beginIntegrationTests()
    }

    class func beginIntegrationTests() {
        var semaphore = DispatchSemaphore(value: 0)
        apiService.beginIntegrationTests(completion: {resource, error in
            if let resource = resource {
                if let manager = resource as? UserWebResource {
                    companyManger = manager
                    companyManagerID = manager.id
                    semaphore.signal()

                }
            }
        })
        _ = semaphore.wait(timeout: DispatchTime.distantFuture)
  }
}

这不起作用。在引擎盖下,有一个对服务器的 alamo fire 调用,它响应用户以用于集成测试。我确实看到服务器在旋转,所以我知道实际的通信正在进行,但我从未进入完成关闭。

我怀疑我不明白 Swift 是如何处理信号量的,而且我不知何故造成了死锁。如果有人有更好的解决方案,我将非常乐意听到。

I get several compiler errors that tell me that I am no longer calling the same waitForExpectations because I am in a class method, not a test case

有道理。您可能想要的是重构,以便您处于测试用例中:

override class func setUp() {
    apiService.baseURL = "http://localhost:3000/"
}

func testIntegrationTests() {
    let urlExpectation = expectation(description: "INTEGRATION TEST")
    apiService.beginIntegrationTests(completion: {resource, error in
        // ...
        urlExpectation.fulfill()
    })

   // not sure what an acceptable timeout would be, I chose this at random
   waitForExpectations(timeout: 25) { error in
       if let error = error {
           print("Error: \(error.localizedDescription)")
       }
   }
}

可以在这里找到包含一些好的测试示例的最佳资源之一:http://nshipster.com/xctestcase/

您可以将期望创建为执行一次性设置并在完成时执行的惰性变量。

在每次测试 setUp() 函数开始时,您可以等待该期望。

None 的测试将 运行 直到完成,并且初始设置将 运行 只有一次。

class WaitForSetup_Tests: XCTestCase {

    lazy var initialSetupFinished: XCTestExpectation = {
        let initialSetupFinished = expectation(description: "initial setup finished")

        initialSetupTask() { // your setup task that executes this closure on completion
            initialSetupFinished.fulfill()
            return
        }

        return initialSetupFinished
    }()

    override func setUp() {
        wait(for: [initialSignOutFinished], timeout: 2.0)
        // do your per-test setup here
    }
}

注意:此解决方案避免使用 override class function setUp() class 方法,因为除了在实例中,我不知道如何使用期望。