Преобразование не-экранирующего закрытия в экранирующий один или другой путь - PullRequest
0 голосов
/ 05 октября 2018

Я создаю шаблон шаблона для легкого переключения между Nimble и XCTAssert для моих модульных тестов.

Итак, у меня есть протокол

protocol Assertable {
  func notNil(_ expression: @autoclosure () throws -> Any?, file: StaticString, line: UInt)
}

Реализация XCTAssert не nil похожа на:

func XCTAssertNotNil(_ expression: @autoclosure () throws -> Any?, _ message: @autoclosure () -> String = default, file: StaticString = #file, line: UInt = #line)

и у Нимбера:

func expect<T>(_ expression: @autoclosure @escaping () throws -> T?, file: FileString = #file, line: UInt = #line) -> Expectation<T>

По сути, единственное отличие состоит в том, что один убегает, а не другой.

Моя проблема в том, что если я объявлю свои шаблоны с @escaping, XCTAssertNotNil (выражение) больше не будет работать, потому что экранированное закрытие никогда не будет рассматриваться как nil, поэтому XCTAssertNotNil всегда будет истинным, а XCTAssertNil всегда будетбыть ложным.

И если я не буду экранировать свои шаблоны, тогда Nimble не будет счастлив, потому что требует экранированных закрытий.

Что делать?

1 Ответ

0 голосов
/ 05 октября 2018

Единственный способ преобразовать неэкранирующее закрытие в экранирующее замыкание - выполнить блок.

func XCTAssertNotNil(_ expression: @autoclosure () throws -> Any?) {
    do {
        let performed = try expression()

        expect(performed)
    } catch {
        expect({ throw error })
    }
}

И наоборот, это не должно быть проблемой:

func expect<T>(_ expression: @autoclosure @escaping () throws -> T?) {
    XCTAssertNotNil(expression)
}
...