Pisanie testów dla funkcjonalności, które wykorzystują requesty może być irytujące. W zależności, jak taki test napiszesz.
Możesz mockować funkcje biblioteki, którą używasz do obsługi reqestów.
Albo przyjąć inne podejście: mockujesz tylko same requesty. To znaczy: jeśli w kodzie zostanie wywołany GET /api/user, ustalasz, że ma zwrócić konkretne dane i tyle!
Na pierwszy rzut oka oba podejścia mogą wydawać się podobne, ale tak nie jest.
W pierwszym podejściu skupiasz się niepotrzebnie na szczegółach: mockujesz konkretną bibliotekę i metodę. Co jeśli w przyszłości będziesz chciał zmienić bibliotekę do obsługi requestów? Po zmianie testy oczywiście się załamią.
Znacznie lepszym rozwiązaniem jest mockowanie samych requestów. Dzięki temu skupiasz się na testowaniu tego, co w rzeczywistości jest ważne: na testowaniu funkcjonalności, a nie szczegółach implementacji
Więc jak mockować requesty?
Jest kilka gotowych bibliotek. W tym wpisie opiszę, jak działa Nock.
Nock
Jest to prosta biblioteka, która pozwala w banalny sposób mockować requesty.
Struktury pozwalają na organizację danych i dzięki temu łatwiejsze ich zarządzanie.
Składnia prezentuje się następująco:
structSomeStruct{
...
}
Żeby stworzyć strukturę, użyj słowa kluczowego struct, a następnie podajesz jej nazwę.
W ciele struktury określasz jej właściwości. Możesz też dodać do niej funkcje. W kontekście struktura funkcje nazywane są metodami.
structProduct{
var name: String = ""var price: Float = 0.0funcdescribe() {
print("Product name: \(name) and price is: \(price)")
}
}
Tworzenie instancji
Tworzenie instancji struktury wygląda tak:
var product = Product()
product.name = "Some product"
product.price = 9.99
product.describe() // Product name: Some product and price is: 9.99
Można też określić wartości struktury w momencie jej tworzenia:
var product = Product(name: "Some product", price: 9.99)
product.describe() // Product name: Some product and price is: 9.99
Uwaga: ważna jest kolejność parametrów. Jeśli pierwszą właściwością w strukturze jest: A, a potem B podczas tworzenia instancji struktury musisz podać wartości, w takiej kolejności.
Czyli w przypadku Product nie możesz napisać tak:
var product = Product(price: 9.99, name: "Some product") // błąd!
Możesz do tworzenia instancji struktury także użyć metody init:
structProduct{
var name: Stringvar price: Floatinit(name: String, price: Float) {
self.name = name
self.price = price
}
funcdescribe() {
print("Product name: \(name) and price is: \(price)")
}
}
Dzięki tej metodzie sam możesz określić kolejność podawanych argumentów przy tworzeniu instancji struktury.
Metody
Jeśli potrzebujesz dodać do struktury metodę, która zmieni swój stan, nie możesz napisać tego w taki sposób:
structCart{
var products: [Product] = []
funcaddProduct(_ product: Product) {
products.append(product)
}
}
var product = Product(name: "Some product", price: 19.99)
var cart = Cart()
cart.addProduct(product) // błąd!
Dlaczego? W Swift struktury są niezmienne ang.: immutable. Oznacza to, że z poziomu struktury nie możesz zmienić jej stanu. No nie do końca.
Wystarczy, że do danej metody dodasz słowo kluczowe mutating:
structCart{
var products: [Product] = []
mutatingfuncaddProduct(_ product: Product) {
products.append(product)
}
}
var product = Product(name: "Some product", price: 19.99)
var cart = Cart()
cart.addProduct(product)
print(cart.products.count) // 1
Stałe struktury
Jeśli instancję struktury określisz za pomocą let:
let product = Product(name: "Some product", price: 19.99)
nie możesz napisać tak:
product.name = "Extra product"// błąd!
Za pomocą let mówisz Swift, że stan obiektu nie może się zmienić.