如何解决带有内部开关盒的单元测试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()
}
}
}
}
我现在所拥有的:
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 举报,一经查实,本站将立刻删除。