Skip to content

Instantly share code, notes, and snippets.

@damodarnamala
Created May 19, 2021 12:32
Show Gist options
  • Save damodarnamala/c79fc5b1abc9ee22ff7ccb0206f48e28 to your computer and use it in GitHub Desktop.
Save damodarnamala/c79fc5b1abc9ee22ff7ccb0206f48e28 to your computer and use it in GitHub Desktop.
MVVM & ViewController Specs
import Combine
class ViewController: UIViewController {
@IBOutlet weak var label: UILabel!
@IBOutlet weak var buttonUser: UIButton!
@IBOutlet weak var buttonPosts: UIButton!
var cancel = Set<AnyCancellable>()
var viewModel = ViewModel()
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func getUsers() {
self.handle(publidher: viewModel.fetch(action: .users))
}
@IBAction func getPosts() {
self.handle(publidher: viewModel.fetch(action: .posts))
}
}
extension ViewController {
private func handle(publidher: AnyPublisher<String, Never>) {
return publidher
.receive(on: RunLoop.main)
.assign(to: \.text!, on: self.label)
.store(in: &cancel)
}
}
class FakeViewModel: ViewModel {
override func fetch(action: ViewModel.Action) -> AnyPublisher<String, Never> {
switch action {
case .posts:
return Just<String>("fakeposts").eraseToAnyPublisher()
case .users:
return Just<String>("fakeusers").eraseToAnyPublisher()
}
}
}
class ViewControllerSpec: XCTestCase {
var subject: ViewController?
func testUserButtonAction() {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let sut = storyboard.instantiateViewController(identifier: "ViewController") as! ViewController
_ = sut.view
sut.viewModel = FakeViewModel()
sut.buttonUser.sendActions(for: .touchUpInside)
let delayExpectation = XCTestExpectation()
delayExpectation.isInverted = true
wait(for: [delayExpectation], timeout: 1)
XCTAssertTrue(sut.label.text == "fakeusers", "should be same as publisher")
}
func testPostButtonAction() {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let sut = storyboard.instantiateViewController(identifier: "ViewController") as! ViewController
_ = sut.view
sut.viewModel = FakeViewModel()
sut.buttonPosts.sendActions(for: .touchUpInside)
let delayExpectation = XCTestExpectation()
delayExpectation.isInverted = true
wait(for: [delayExpectation], timeout: 1)
XCTAssertTrue(sut.label.text == "fakeposts", "should be same as publisher")
}
}
import Foundation
import Combine
class ViewModel {
private let interator: Interactor
init() {
self.interator = Interactor()
}
func fetch(action: Action) -> AnyPublisher<String, Never> {
return interator.fetch(action: action)
}
}
extension ViewModel {
enum Action {
case users
case posts
}
private class Interactor {
// calling api or some heavy stuff and modify return type
func fetch(action: Action) -> AnyPublisher<String, Never> {
switch action {
case .posts:
return Just<String>("posts....")
.eraseToAnyPublisher()
case .users:
return Just<String>("users....")
.delay(for: .seconds(1), scheduler: RunLoop.main)
.eraseToAnyPublisher()
}
}
}
}
import Combine
class ViewModelSpec: XCTestCase {
func testViewModelFetchUsers() {
let viewModelodel: ViewModel = FakeViewModel()
var userText = ""
let expectation = self.expectation(description: "user")
_ = viewModelodel.fetch(action: .users).sink { (str) in
userText = str
expectation.fulfill()
}
waitForExpectations(timeout: 2)
XCTAssertTrue(userText == "fakeusers", "should be same as publisher")
}
func testViewModelFetchPosts() {
let viewModelodel: ViewModel = FakeViewModel()
var userText = ""
let expectation = self.expectation(description: "posts")
_ = viewModelodel.fetch(action: .posts).sink { (str) in
userText = str
expectation.fulfill()
}
waitForExpectations(timeout: 2)
XCTAssertTrue(userText == "fakeposts", "should be same as publisher")
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment