2014-11-13 18 views
26

Tôi đang cố gắng tìm hiểu cách kiểm tra tốt nhất ứng dụng sử dụng Alamofire để giúp đồng bộ hóa với dữ liệu máy chủ.Kiểm tra lưu lượng HTTP trong ứng dụng Alamofire

Tôi muốn có thể kiểm tra mã của mình sử dụng Alamofire và xử lý phản hồi JSON từ máy chủ. Tôi muốn thử các thử nghiệm đó để tôi có thể cung cấp dữ liệu phản hồi dự kiến ​​cho các thử nghiệm đó mà không phải chịu lưu lượng truy cập mạng thực.

Bài đăng trên blog này (http://nshipster.com/xctestcase/) mô tả cách dễ dàng để giả lập đối tượng trong Swift - nhưng tôi không chắc chắn cách thực hiện điều đó với Alamofire và các câu trả lời bị xích.

Tôi có giả mạo Người quản lý không? yêu cầu? Phản ứng? Bất kỳ trợ giúp sẽ được đánh giá cao!

+1

Nghĩa đen tìm kiếm điều tương tự ngay bây giờ ... –

+0

đã bạn con nó ra? –

+0

Xem http://stackoverflow.com/questions/10807480/stubbing-mocking-up-webservices-for-an-ios-app – mattt

Trả lời

19

Tôi đang thêm một câu trả lời khác vì tôi vừa tìm thấy cách tiếp cận này theo ý kiến ​​của tôi dễ đọc và dễ sử dụng hơn.

Tôi đã tạo một lớp Alamofire giả chỉ chứa các hàm và các loại cần thiết để kiểm tra. Bây giờ tôi đưa tệp này vào mục tiêu thử nghiệm thay vì Alamofire thực.Ví dụ: tôi đã tạo phiên bản của lớp Request nơi tôi xác định một vài biến tĩnh mà tôi định giá trị tùy thuộc vào thử nghiệm và đối với lớp này, tôi đã chỉ triển khai init và hàm responseJSON.

public class Request { 

    var request:String? 
    struct response{ 
     static var data:NSHTTPURLResponse? 
     static var json:AnyObject? 
     static var error:NSError? 
    } 

    init (request:String){ 
     self.request = request 
    } 

    public func responseJSON(options: NSJSONReadingOptions = .AllowFragments, completionHandler: (NSURLRequest, NSHTTPURLResponse?, AnyObject?, NSError?) -> Void) -> Self { 

     completionHandler(NSURLRequest(URL: NSURL(string:self.request!)!), Request.response.data, Request.response.json, Request.response.error) 
     return self 
    } 
} 

Bây giờ tôi có thể thử một phản ứng trong một thử nghiệm:

func testMytestFunction(){ 
    var HTMLResponse = NSHTTPURLResponse(URL: NSURL(string: "myurl")!, statusCode: 200, HTTPVersion: "HTTP/1.1", headerFields: nil) 

    Request.response.data = HTMLResponse 
    Request.response.json = LoadDataFromJSONFile("MyJsonFile") 

    request(.POST, "myurl", parameters: nil, encoding: ParameterEncoding.JSON).responseJSON { 
     (request, response, JSON, error) -> Void in 
     // the JSON and response variable now contains exactly the data that you have passed to Request.response.data and Request.response.json 
    } 
} 

Chức năng yêu cầu được định nghĩa ở đây:

public func request(method: Method, URLString: URLStringConvertible, parameters: [String: AnyObject]? = nil, encoding: ParameterEncoding = .URL) -> Request { 

    return Request(request: URLString.URLString) 
} 

public func request(URLRequest: URLRequestConvertible) -> Request { 

    return Request(request: "fakecall") 
} 
+6

Bao giờ nghĩ về việc chia sẻ điều này trên Github? Nó có lẽ sẽ tiết kiệm một số thời gian và chứng minh là rất hữu ích –

+0

bạn biết - đó cũng là một khuôn khổ giả NSURLSession - DVR - trên github https://github.com/venmo/DVR –

+0

Phương pháp yêu cầu mà bạn đang gọi trong testMytestChức năng kiểm tra? –

1

Đang chờ câu trả lời bằng @mattt Tôi đăng một ví dụ về mã của tôi.

Giả sử chúng tôi có lớp học Client chịu trách nhiệm gọi một dịch vụ web đơn giản. Lớp này triển khai thực hiện một hàm có tên là userSignIn thực hiện đăng nhập bằng WS.

Đây là mã cho userSignIn chức năng:

func userSignIn(
     #email:String, 
     password:String, 
     completionHandler: (Bool, String?, NSError?) -> Void 
     )-> Void 
     { 

      var parameters:[String:AnyObject] = [ 
       "email":email, 
       "password":password, 
      ] 


      Alamofire.request(.POST, Client.urlPath, parameters: parameters, encoding: ParameterEncoding.JSON).responseJSON { 
       (request, response, JSON, responseError) -> Void in 

       // Setup callback params 

       // HERE WE INJECT THE "FAKE" DATA-------- 
       var operationComplete = false 
       var accessToken:String? 
       var error:NSError? 
       // -------------------------------------- 

       if let statusCode = response?.statusCode { 

        // Check for errors and build response data 
        (operationComplete, accessToken, error) = self.checkSignInResponse(statusCode, JSON: JSON) 
       } 

       // Call the completion handler 
       completionHandler(operationComplete, accessToken, error) 
      } 
    } 

Mục đích của chức năng là để nhận mã từ dịch vụ web nếu thông tin được truyền bởi người sử dụng là chính xác.

Chức năng checkSignInResponse (tôi không khai báo mã của nó kể từ khi nó không phải là hữu ích cho các câu trả lời) có vai trò để valorise 3 biến operationComplete, accessTokenerror tùy thuộc vào phản ứng JSON nhận.

Bây giờ, 3 biến có giá trị chúng tôi gọi là completionHandler khi sử dụng chúng.

Làm thế nào để giả lập chức năng này ?!

Để mô phỏng đáp ứng, tôi ghi đè hàm userSignIn trực tiếp vào hàm kiểm tra (như được giải thích bởi bài viết NSHipster).

func testUserSignIn_whenParamsAreInvalid(){ 

    class MockClient:Client { 

     override func userSignIn(#email: String, password: String, completionHandler: 
      (Bool, String?, NSError?) -> Void) { 

      // Set callback params 
      var operationComplete = false 
      var accessToken:String? = nil 
      var error:NSError? = NSError(domain: "Testing", code: 99, userInfo: nil) 

      completionHandler(operationComplete, accessToken, error) 
     } 
    } 

    signInViewController!.client = MockClient() 
    signInViewController!.loadView() 

    fillRegisterFieldsWithDataAndSubmit(femail(), password: fpassword()) 

    XCTAssertNotNil(signInViewController!.error, "Expect error to be not nil") 

} 

sau đó tôi thay thế các client bên trong bộ điều khiển điểm cho rằng tôi đang thử nghiệm sử dụng của tôi "chế giễu" khách hàng. Trong trường hợp này, tôi kiểm tra rằng bộ điều khiển chuyển tới thông tin chức năng không hợp lệ vì vậy tôi kiểm tra xem thuộc tính error của bộ điều khiển không phải là không. Để ép buộc dữ liệu này, tôi chỉ cần đặt operationComplete thành sai và tôi tạo một số NSError.

Điều đó có ý nghĩa gì với bạn không? Tôi không chắc rằng thử nghiệm này là một thử nghiệm tốt ... nhưng ít nhất tôi có thể xác minh luồng dữ liệu.

7

Câu hỏi này được già đi, nhưng tôi chỉ gặp nhau vấn đề và giải pháp rất dễ dàng khi sử dụng OHHTTPStubs.

OHHTTPStubs chỉ mô phỏng phản hồi bạn nhận được từ NSURLSession, vì vậy nó hoạt động tốt với Alamofire và bạn nhận được mức độ phù hợp rất tốt cho đường dẫn mã của mình.

Ví dụ, trong trường hợp thử nghiệm của bạn, chỉ cần thử phản ứng sử dụng:

OHHTTPStubs.stubRequestsPassingTest({ 
    (request: NSURLRequest) -> Bool in 
    return request.URL!.host == "myhost.com" 
    }, withStubResponse: { 
    (request: NSURLRequest) -> OHHTTPStubsResponse in 
    let obj = ["status": "ok", "data": "something"] 
    return OHHTTPStubsResponse(JSONObject: obj, statusCode:200, headers:nil) 
}) 
+3

làm thế nào tiêm OHHTTPStubs để kiểm tra đơn vị., Tôi sử dụng OHHTTPStubs trong bài kiểm tra đơn vị, nhưng nó không hoạt động – Leo

Các vấn đề liên quan