Pour éviter de faire de véritables appels réseaux dans nos tests, nous allons créer un jeu de données de test. Ces données vont simuler les différentes réponses que l'on peut recevoir avec des appels réseaux.
Pour cela, nous allons créer de fausses données de réponse pour nos tests, soit à partir de véritables données récupérées sur l'API Forismatic, soit en créant nous-mêmes nos données.
Mettez en place les tests
Pour faire tout cela, il nous faut une target dans notre projet Xcode pour écrire nos tests unitaires. Nous allons la créer et créer ensuite un fichier de test unitaire : QuoteServiceTestCase.swift
.
Toutes les instructions pour faire cela sont détaillées dans ce cours.
Je vous laisse faire. Vous devriez obtenir ceci dans votre navigateur :
Récupérez des données de test
Nous allons récupérer nos données de test directement depuis l'API Forismatic pour qu'elles soient les plus proches possible de la réalité.
Pour cela, lancez simplement un appel sur Postman et copiez la réponse :
Ensuite, dans Xcode, créez un nouveau fichier ( cmd + n ) et choisissez Empty :
Puis nommez-le Quote.json
et sauvegardez-le du côté des tests.
Dedans, vous pouvez coller la réponse récupérée dans Postman.
Nous avons maintenant un joli fichier JSON dans notre projet, que nous allons pouvoir utiliser dans nos tests à la place d'un véritable appel réseau.
Remplissez la classe FakeResponseData
Pour pouvoir récupérer les données sur le fichier et les utiliser dans nos tests, nous allons créer une classe que nous allons appeler FakeResponseData
, et dont le rôle sera de gérer les données de test.
C'est fait ? Bien ! Réfléchissons maintenant aux données que nous allons essayer de simuler dans cette classe. Cette classe doit nous permettre de simuler la réponse d'un serveur lors de nos deux appels réseaux.
Du coup, retournons voir un peu à quoi ressemble cette réponse :
task = session.dataTask(with: request) { (data, response, error) in
// (...)
}
La réponse contient trois paramètres, data
, response
et error
. Pour simuler la réponse des deux API, nous allons avoir besoin de simuler ces trois paramètres pour chaque appel. Je vous propose de commencer par le plus simple : response
.
Simuler response
Pour simuler response
, nous allons créer deux instances de HTTPURLResponse
:
Une qui a pour code 200 : c'est le cas où tout va bien.
Une avec le code 500 : quand ça ne fonctionne pas.
static let responseOK = HTTPURLResponse(
url: URL(string: "https://openclassrooms.com")!,
statusCode: 200, httpVersion: nil, headerFields: [:])!
static let responseKO = HTTPURLResponse(
url: URL(string: "https://openclassrooms.com")!,
statusCode: 500, httpVersion: nil, headerFields: [:])!
Ces deux réponses vont nous permettre de tester nos cas d'erreur liés à un mauvais code HTTP.
Simuler error
Dans notre code, on ne s'intéresse pas à l'erreur en elle-même mais seulement à la présence ou non d'une erreur. Donc nous allons juste créer une erreur toute simple comme ceci :
class QuoteError: Error {}
static let error = QuoteError()
Ici, on doit créer une classe QuoteError
qui implémente le protocole Error
. En effet, Error
étant un protocole, on ne peut pas en obtenir une instance. Donc je crée une classe pour y parvenir.
Simulez data
Nous allons maintenant nous attaquer au plus gros morceau : simuler les véritables données renvoyées par les API. Nous allons simuler trois données différentes :
le JSON renvoyé par Forismatic ;
un JSON endommagé qui ne correspond pas au format que nous attendons ;
les données renvoyées par Unsplash.
Toutes ces données doivent être de type Data
.
Simulez le JSON renvoyé par Forismatic
Nous allons utiliser le fichier que nous avons créé en début de chapitre. Notre objectif va être ici de récupérer les données du fichier dans le code.
Pour cela, il faut d'abord récupérer le paquet dans lequel se trouve notre fichier. Ce paquet, on l'appelle Bundle
en Swift. Et il nous faut commencer par récupérer le bon bundle
: celui dans lequel se trouve notre fichier Quote.json
.
Il y a deux bundle
dans notre projet, un par target, donc un pour les tests et un pour l'application.
On va récupérer celui des tests comme ceci :
let bundle = Bundle(for: FakeResponseData.self)
Ici je demande le bundle
qui contient le fichier de la classe dans laquelle je me trouve : FakeResponseData
. Ce sera du coup le bundle
des tests, celui qui contient aussi notre fichier Quote.json
.
Une fois qu'on a le bundle
, on récupère l'URL à laquelle se trouve notre fichier en indiquant le nom et l'extension du fichier que l'on cherche :
let url = bundle.url(forResource: "Quote", withExtension: "json")!
Enfin, je récupère les données contenues à cette URL via l'initialiseur init(contentsOf: URL)
de Data
:
let data = try! Data(contentsOf: url)
On va mettre tout ça dans une propriété calculée et ça donne ceci :
static var quoteCorrectData: Data? {
let bundle = Bundle(for: FakeResponseData.self)
let url = bundle.url(forResource: "Quote", withExtension: "json")!
return try! Data(contentsOf: url)
}
Et voilà ! Nous avons les données de notre fichier dans une belle propriété qu'on va pouvoir utiliser dans nos tests.
Simulez un JSON endommagé
Pour simuler un JSON endommagé, il suffit d'avoir des données qui n'ont rien à voir avec un fichier JSON. Pour cela, on va créer une constante de type Data
dans laquelle on va mettre la valeur de notre choix.
Ma méthode préférée pour créer de fausses données, c'est l'encodage des String
:
static let quoteIncorrectData = "erreur".data(using: .utf8)!
J'utilise la méthode data(using:)
sur une string de mon choix, et je précise l'encodage le plus classique. La méthode renvoie une valeur de type Data
.
Les données générées par cet encodage n'auront rien à voir avec un JSON, et cela va nous permettre de tester le cas où les données ne sont pas au format attendu.
Simulez les données de l'image
Enfin, pour simuler les données de l'image, je vais faire exactement la même chose :
static let imageData = "image".data(using: .utf8)!
Et voilà ! Toutes nos données sont prêtes et elles vont nous permettre de simuler toutes les différentes réponses que nous pouvons recevoir de nos deux appels.
En résumé
Pour créer votre jeu de données afin de faire vos tests :
Créez une target spécifique pour vos tests unitaires et ajoutez-y un fichier de test.
Rajoutez un fichier de type Empty afin d’y ajouter une fausse réponse JSON.
Définissez une classe pour simuler la réponse de
dataTask
et ses paramètres (response, data et error).Un Bundle est un paquet, il y en a un par target.
Récupérez les données simulées de votre fichier JSON en utilisant la référence sur le bundle.
Vous avez créé votre jeu de données, bravo ! 🥳 Dans le prochain chapitre, nous allons préparer notre classe QuoteService
à être testée.