2016-01-14 1 views
4

Я изучаю Test Driven Development в Swift. Я ударил стену, когда понял, что шаблон делегата, который я регулярно использую для асинхронных запросов, трудно проверить. Я узнал, что если что-то трудно проверить, дизайн схемы реализации, возможно, будет лучше. Это меня смущает, потому что я считаю, что шаблон делегата, который я использую, является общим, и мне интересно, как другие справились с этой проблемой.Тестируемый шаблон асинхронного проектирования в Swift

Узор:

Я написал службу, которая выполняет асинхронный запрос в статической функции, которая принимает экземпляр делегата. Экземпляр делегата соответствует протоколу, который требует реализации метода успеха и отказа. Я придумал пример, который попадает на сайт Google.com. В этом примере игнорируйте проблемы безопасности типа. Фактический код, который я запускаю, чтобы попасть в конечную точку и проанализировать JSON, безопаснее. Я просто хотел, чтобы придумать очень небольшой фрагмент кода, чтобы изобразить вопрос, который вызывает трудности при тестировании:

protocol GoogleServiceDelegate { 
    func gotGoogle(str: String); 
    func gotError(str: String); 
} 

struct GoogleService { 
    static func getGoogle(delegate: GoogleServiceDelegate) { 
     let url: NSURL! = NSURL(string: "http://google.com") 
     NSURLSession.sharedSession().dataTaskWithURL(url) { data, response, error in 
      if let data = data { 
       let str: NSString! = NSString(data: data, encoding: NSUTF8StringEncoding) 
       delegate.gotGoogle(str as String) 
      } else { 
       delegate.gotError("\(error)") 
      } 
     } 
    } 
} 

Вот тест, который иллюстрирует эту проблему:

class AsyncTestingTests: XCTestCase { 

    func testExample() { 
     let responseExpectation = expectationWithDescription("Got google response!") 

     struct GoogleDelegate: GoogleServiceDelegate { 
      func gotGoogle(str: String) { 
       // expectations about response 
       responseExpectation.fulfill() 
      } 

      func gotError(str: String) { 
       // expectations about error 
       responseExpectation.fulfill() 
      } 
     } 

     let myGoogleServiceDelegate = GoogleDelegate() 
     GoogleService.getGoogle(myGoogleServiceDelegate) 

     waitForExpectationsWithTimeout(5) { _ in 
      print("Never got a response from Google :(") 
     } 
    } 
} 

Проблема возникает в две линии .fulfill(). Я получаю следующее сообщение об ошибке от Xcode:

Struct декларация не может закрыть над значением «responseExpectation» определено в внешней области

Я понимаю ошибку, но не уверен, что нужно подстраивать ... Есть обходной путь для этого, который я могу использовать в тесте, или есть лучший (легко проверяемый) шаблон для асинхронных обратных вызовов, чем то, что я пытаюсь сделать? Если вы знаете о более надежном тестируемом решении, не могли бы вы потратить время, чтобы записать пример?

ответ

1

Да, вы не можете закрыть переменные, определенные за пределами структуры, обходным путем, нам нужно использовать замыкания/функции и передать их в структуру. Методы в struct могут ссылаться на него, когда они получают ответ.

func testExample() { 
     let responseExpectation = expectationWithDescription("Got google response!") 

//Let a function capture the fulfilling of the expectation 
     func fullFillExpectation(){ 

     responseExpectation.fullFill() 
     } 

     struct GoogleDelegate: GoogleServiceDelegate { 

     var fullFiller : (()->Void)! 
     func gotGoogle(str: String) { 
      // expectations about response via invoke the closure 
      fullFiller() 
     } 

     func gotError(str: String) { 
      // expectations about error - invoke the closure 
      fullFiller() 
     } 
     } 

     //Create the delegate with full filler function. 
     let myGoogleServiceDelegate = GoogleDelegate(fullFiller: fullFillExpectation) 
     GoogleService.getGoogle(myGoogleServiceDelegate) 

     waitForExpectationsWithTimeout(5) { _ in 
     print("Never got a response from Google :(") 
     } 
    } 
    } 

PS: Я не мог проверить это, пожалуйста, протестируйте и сообщите мне.

+1

Это сработало! Спасибо! – pachun

+1

Полезно знать: - – Shripada

Смежные вопросы