Skip to content

Instantly share code, notes, and snippets.

@sanjayhub
Last active October 7, 2022 11:30
Show Gist options
  • Save sanjayhub/cccb5ff5058f70fe481a9a69db4e65b9 to your computer and use it in GitHub Desktop.
Save sanjayhub/cccb5ff5058f70fe481a9a69db4e65b9 to your computer and use it in GitHub Desktop.
UnitTesting Asynchronous code
//
// DispatchInMainQueueTests.swift
// DispatchInMainQueueTests
//
// Created by Kumar, Sanjay (623) on 29/09/22.
//
import XCTest
@testable import DispatchInMainQueue
class DispatchInMainQueueTests: XCTestCase {
func test_viewDidLoad_rendersLabelTextFromService() {
let service = ServiceSpy()
let sut = ViewController.make(service: service)
sut.loadViewIfNeeded()
XCTAssertEqual(sut.label.text, "Loading...")
service.completion?("Loaded")
XCTAssertEqual(sut.label.text, "Loaded")
}
}
private class ServiceSpy: Service {
var completion: ((String) -> Void)?
func load(completion: @escaping (String) -> Void) {
self.completion = completion
}
}
//
// SceneDelegate.swift
// DispatchInMainQueue
//
// Created by Kumar, Sanjay (623) on 29/09/22.
//
import UIKit
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let scene = (scene as? UIWindowScene) else { return }
let service = MainQueueDispatchDecorator(AsyncService())
let vc = ViewController.make(service: service)
window = UIWindow(windowScene: scene)
window?.rootViewController = vc
window?.makeKeyAndVisible()
}
}
final class AsyncService: Service {
func load(completion: @escaping (String) -> Void) {
DispatchQueue.global().asyncAfter(deadline: .now() + 2) {
completion("Hello swift dev")
}
}
}
private final class MainQueueDispatchDecorator: Service {
private let decoratee: Service
init(_ decoratee: Service) {
self.decoratee = decoratee
}
func load(completion: @escaping (String) -> Void) {
decoratee.load { result in
executeInMainThread {
completion(result)
}
}
}
}
func executeInMainThread(_ work: @escaping () -> Void) {
if Thread.isMainThread {
work()
} else {
DispatchQueue.main.async(execute: work)
}
}
// ViewController.swift
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var label: UILabel!
private var service: Service!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.label.text = "Loading..."
service.load { [weak self] text in
self?.label.text = text
}
}
}
extension ViewController {
static func make(service: Service) -> ViewController {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
return storyboard.instantiateViewController(identifier: "ViewController") {
let vc = ViewController(coder: $0)
vc?.service = service
return vc
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment