Last active
January 2, 2022 20:59
-
-
Save agiokas/35b681c0b02e2e9eeb5d034477792213 to your computer and use it in GitHub Desktop.
ViewModel test example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
final class Datasource { | |
func pets() -> [Pet] { | |
[ | |
Pet(id: "1", name: "Max", ownerId: "1"), | |
Pet(id: "2", name: "Azor", ownerId: "1"), | |
Pet(id: "3", name: "Monty", ownerId: "2"), | |
Pet(id: "4", name: "Zizou", ownerId: "3"), | |
] | |
} | |
func persons() -> [Person] { | |
[ | |
Person(id: "1", firstName: "Apo", lastName: ""), | |
Person(id: "3", firstName: "Melanie", lastName: ""), | |
Person(id: "4", firstName: "Mustermann", lastName: ""), | |
] | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
protocol DatasourceInterface { | |
func pets() -> [Pet] | |
func persons() -> [Person] | |
} | |
final class Datasource: DatasourceInterface { | |
func pets() -> [Pet] { | |
[ | |
Pet(id: "1", name: "Max", ownerId: "1"), | |
Pet(id: "2", name: "Azor", ownerId: "1"), | |
Pet(id: "3", name: "Monty", ownerId: "2"), | |
Pet(id: "4", name: "Zizou", ownerId: "3"), | |
] | |
} | |
func persons() -> [Person] { | |
[ | |
Person(id: "1", firstName: "Apo", lastName: ""), | |
Person(id: "3", firstName: "Melanie", lastName: ""), | |
Person(id: "4", firstName: "Mustermann", lastName: ""), | |
] | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
struct Person: Identifiable { | |
let id: String | |
let firstName: String | |
let lastName: String | |
} | |
struct Pet: Identifiable { | |
let id: String | |
let name: String | |
let ownerId: String | |
} | |
final class MyViewModel { | |
private let persons: [Person] | |
private let pets: [Pet] | |
init(persons: [Person], pets: [Pet]) { | |
self.persons = persons | |
self.pets = pets | |
} | |
func listData() -> [MyViewModel.Data] { | |
pets.compactMap { pet in | |
guard let owner = persons.first(where: { $0.id == pet.ownerId }) else { | |
return nil | |
} | |
return MyViewModel.Data(petName: pet.name, | |
owner: owner.firstName) | |
} | |
} | |
struct Data: Equatable { | |
let petName: String | |
let owner: String | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
final class MyViewModel2 { | |
private let datasource = Datasource() | |
func listData() -> [MyViewModel.Data] { | |
datasource | |
.pets() | |
.compactMap { pet in | |
guard let owner = datasource | |
.persons() | |
.first(where: { $0.id == pet.ownerId }) else { | |
return nil | |
} | |
return Data(petName: pet.name, owner: owner.firstName) | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
final class MyViewModel2 { | |
private let datasource: DatasourceInterface | |
init(datasource: DatasourceInterface) { | |
self.datasource = datasource | |
} | |
func listData() -> [MyViewModel.Data] { | |
datasource | |
.pets() | |
.compactMap { pet in | |
guard let owner = datasource | |
.persons() | |
.first(where: { $0.id == pet.ownerId }) else { | |
return nil | |
} | |
return MyViewModel.Data(petName: pet.name, owner: owner.firstName) | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import XCTest | |
@testable import UnitTesting101 | |
final class MyViewModel2Tests: XCTestCase { | |
func testListData() { | |
let viewModel = MyViewModel2(datasource: DatasourceMock()) | |
let expectedData: [MyViewModel.Data] = [ | |
.init(petName: "Max", owner: "Apo"), | |
.init(petName: "Azor", owner: "Apo"), | |
.init(petName: "Zizou", owner: "Melanie"), | |
] | |
XCTAssertEqual(viewModel.listData(), expectedData) | |
} | |
} | |
struct DatasourceMock: DatasourceInterface { | |
func pets() -> [Pet] { | |
samplePets() | |
} | |
func persons() -> [Person] { | |
samplePersons() | |
} | |
} | |
private func samplePets() -> [Pet] { | |
[ | |
Pet(id: "1", name: "Max", ownerId: "1"), | |
Pet(id: "2", name: "Azor", ownerId: "1"), | |
Pet(id: "3", name: "Monty", ownerId: "2"), | |
Pet(id: "4", name: "Zizou", ownerId: "3"), | |
] | |
} | |
private func samplePersons() -> [Person] { | |
[ | |
Person(id: "1", firstName: "Apo", lastName: ""), | |
Person(id: "3", firstName: "Melanie", lastName: ""), | |
Person(id: "4", firstName: "Mustermann", lastName: ""), | |
] | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
final class MyViewModel3 { | |
private let datasource: UserDefaults | |
init(datasource: UserDefaults) { | |
self.datasource = datasource | |
} | |
func listData() -> [MyViewModel.Data] { | |
pets() | |
.compactMap { pet in | |
guard let owner = persons() | |
.first(where: { $0.id == pet.ownerId }) else { | |
return nil | |
} | |
return MyViewModel.Data(petName: pet.name, owner: owner.firstName) | |
} | |
} | |
private func pets() -> [Pet] { | |
guard let data = datasource.data(forKey: "Pets"), | |
let petsData = try? PropertyListDecoder().decode([Pet].self, from: data) else { | |
return [] | |
} | |
return petsData | |
} | |
private func persons() -> [Person] { | |
guard let data = datasource.data(forKey: "Persons"), | |
let personsData = try? PropertyListDecoder().decode([Person].self, from: data) else { | |
return [] | |
} | |
return personsData | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import XCTest | |
@testable import UnitTesting101 | |
final class MyViewModel3Tests: XCTestCase { | |
func testListData() throws { | |
guard let userDefaults = UserDefaults(suiteName: "MyViewModel3Tests") else { | |
XCTFail("User defaults needed") | |
return | |
} | |
let encodedPets = try PropertyListEncoder().encode(samplePets()) | |
let encodedPersons = try PropertyListEncoder().encode(samplePersons()) | |
userDefaults.set(encodedPets, forKey: "Pets") | |
userDefaults.set(encodedPersons, forKey: "Persons") | |
userDefaults.synchronize() | |
let viewModel = MyViewModel3(datasource: userDefaults) | |
let expectedData: [MyViewModel.Data] = [ | |
.init(petName: "Max", owner: "Apo"), | |
.init(petName: "Azor", owner: "Apo"), | |
.init(petName: "Zizou", owner: "Melanie"), | |
] | |
XCTAssertEqual(viewModel.listData(), expectedData) | |
} | |
} | |
private func samplePets() -> [Pet] { | |
[ | |
Pet(id: "1", name: "Max", ownerId: "1"), | |
Pet(id: "2", name: "Azor", ownerId: "1"), | |
Pet(id: "3", name: "Monty", ownerId: "2"), | |
Pet(id: "4", name: "Zizou", ownerId: "3"), | |
] | |
} | |
private func samplePersons() -> [Person] { | |
[ | |
Person(id: "1", firstName: "Apo", lastName: ""), | |
Person(id: "3", firstName: "Melanie", lastName: ""), | |
Person(id: "4", firstName: "Mustermann", lastName: ""), | |
] | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
final class MyViewModel3_v2Tests: XCTestCase { | |
func testListData() throws { | |
let userDefaults = UserDataStoreInterfaceMock() | |
let encodedPets = try PropertyListEncoder().encode(samplePets()) | |
let encodedPersons = try PropertyListEncoder().encode(samplePersons()) | |
userDefaults.dataStub = { key in | |
if key == "Persons" { | |
return encodedPersons | |
} | |
if key == "Pets" { | |
return encodedPets | |
} | |
return nil | |
} | |
let viewModel = MyViewModel3(datasource: userDefaults) | |
let expectedData: [MyViewModel.Data] = [ | |
.init(petName: "Max", owner: "Apo"), | |
.init(petName: "Azor", owner: "Apo"), | |
.init(petName: "Zizou", owner: "Melanie"), | |
] | |
XCTAssertEqual(viewModel.listData(), expectedData) | |
} | |
} | |
final class UserDataStoreInterfaceMock: UserDataStoreInterface { | |
var dataStub: (String) -> Data? = { _ in nil } | |
func data(forKey defaultName: String) -> Data? { | |
dataStub(defaultName) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import XCTest | |
@testable import UnitTesting101 | |
final class MyViewModelTests: XCTestCase { | |
func testListData() { | |
let viewModel = MyViewModel(persons: samplePersons(), pets: samplePets()) | |
let expectedData: [MyViewModel.Data] = [ | |
.init(petName: "Max", owner: "Apo"), | |
.init(petName: "Azor", owner: "Apo"), | |
.init(petName: "Zizou", owner: "Melanie"), | |
] | |
XCTAssertEqual(viewModel.listData(), expectedData) | |
} | |
private func samplePets() -> [Pet] { | |
[ | |
Pet(id: "1", name: "Max", ownerId: "1"), | |
Pet(id: "2", name: "Azor", ownerId: "1"), | |
Pet(id: "3", name: "Monty", ownerId: "2"), | |
Pet(id: "4", name: "Zizou", ownerId: "3") | |
] | |
} | |
private func samplePersons() -> [Person] { | |
[ | |
Person(id: "1", firstName: "Apo", lastName: ""), | |
Person(id: "3", firstName: "Melanie", lastName: ""), | |
Person(id: "4", firstName: "Mustermann", lastName: ""), | |
] | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment