微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

带有内部开关盒的单元测试API调用

如何解决带有内部开关盒的单元测试API调用

我正在尝试对具有不同设置模式的类进行单元测试。

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?
}


这将检查模式是否正确,但是我尝试更进一步,并检查是否根据模式设置了正确的项目数。并想直接从fetchInfo()调用XCTestCase方法并只验证模型计数。

我看过的所有教程和指南都只是谈论用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和singleton的内容。我决定继续使用类继承。我尝试避免使用协议,但是坦率地说,使用类要容易得多!

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
    }
}

在我的测试课中:

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实例化对象,我无法找到其他方法,所以必须重构!

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。