簡體   English   中英

單元測試 API 使用內部開關盒調用

[英]Unit test API Call with internal switch case

我正在嘗試對具有不同設置模式的 class 進行單元測試。

class Controller{

    enum Mode{
        case listing
        case pages(String?)
    }

    private (set) var mode : Mode = .listing
    private (set) var models = [Model]()

    init() {
        ...
    }

    init(id : String) {
        mode = .pages(id)
    }

    func fetchInfo(){

        switch mode{
           case .listing: 
               ApiManager.firstNetworkCall(){ (json, error) in ... 
                    setupModel()
               }
           case .pages(let id):
               ApiManager.secondNetworkCall(id : id){ (json, error) in ... 
                    setupModel()
               }
        }
    }
}

這兩個都將使用不同數量的數據更新models數組。

我現在擁有的:

var controller : Controller!

override func setUpWithError() throws {

    // Put setup code here. This method is called before the invocation of each test method in the class.
    try super.setUpWithError()
    controller = Controller()
}

override func tearDownWithError() throws {
    // Put teardown code here. This method is called after the invocation of each test method in the class.
    controller = nil
    try super.tearDownWithError()
}

func testDefaultListingMode() throws {

    switch controller.mode{
       case .listing:
           XCTAssertTrue(true)
       default:
           XCTAssertFalse(false)
    }
}

func testAPISetup() throws {

    controller.fetchInfo()
    //now what?
}


這會檢查模式是否正確,但我正在嘗試 go 進一步檢查是否根據模式設置了正確的項目數。 並且想直接從XCTestCase調用fetchInfo()方法並驗證 model 計數。

我看到的所有教程和指南都只是談論使用URLSession偽造行為。 但是 API 調用取決於fetchInfo方法內部作為內部檢查發生的模式,並且是唯一暴露給其他類的方法。 我只想測試該方法(以防該方法內部發生故障導致錯誤)。

我該怎么做呢? 我不知道如何完成testAPISetup()方法。

我擁有的網絡:

class NetworkingManager{
   static var alamoFireManager = Session.default

   static func POST(...., completion : ()->()) {
       sendRequest(....., completion : completion)
   }

   private static func sendRequest(...., completion : ()->()) {
       let request = alamoFireManager.request(.....)
       request.responseJSON{

           completion()
       }
   }
}

class APIManager{

    static func firstNetworkCall(completion : ()->()){
        NetworkingManager.POST(..., completion : completion)
    }
}

我不得不更改上述內容並刪除所有提及 static 和單身人士。 我決定使用 go 提前使用 class inheritance。 我試圖避免它並使用協議,但坦率地說,使用類更容易!

class NetworkingManager{

    private (set) var sessionManager: Session

    init(config : URLSessionConfiguration = .default){

        config.timeoutIntervalForResource = 8.0
        config.timeoutIntervalForRequest = 8.0

        self.sessionManager = Session(configuration: config)
    }

    func request(...) {
         //hit alamofire
    }
}

class APIManager : NetworkingManager{

    override init(config: URLSessionConfiguration = .default) {
        super.init(config: config)
    }
    
    //other methods
    ...
}

class Controller{

    private let apiManager : APIManager
    init(manager : APIManager = APIManager()){
        self.apiManager = manager
    }
}

在我的測試 class 中:

override func setUpWithError() throws {

    // Put setup code here. This method is called before the invocation of each test method in the class.
    try super.setUpWithError()

    let config = URLSessionConfiguration.ephemeral
    apiManager = APIManager(config : config)
    controller = Controller(manager : apiManager)
}

func testApiCalled() throws{

    controller.fetchNecessaryInfo()
    //had to add one second delay as alamofire adds the request on another queue. Wasn't able to put it on main queue.
    sleep(1)
    let promise = expectation(description: "Check request called")
    apiManager.sessionManager.session.getAllTasks { (taskArray) in

       if taskArray.count > 1{
           XCTFail("Multiple requests when there should be only one")
       }
            
       if let task = taskArray.first, let request = task.currentRequest{
           if let string = request.url?.absoluteString{
               XCTAssert(...)
           }else{
               XCTFail("Incorrect URL")
           }
       }else{
            XCTFail("Somehow no task exists. So this is an error")
       }

       promise.fulfill()
    }

    wait(for: [promise], timeout: 1.0)
}

如果不必為 APIManager 實例化 object,我想不出任何其他方法,所以不得不重構!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM