Tester les ViewModels dans une architecture en couches peut être complexe.
Sans tests adéquats, les bugs peuvent apparaître, compromettant l’intégrité des données et l’expérience utilisateur.
Cet article explore des méthodes pour tester efficacement les ViewModels utilisant MVVM et Clean Architecture.
Développez des applications Android solides, fiables et efficaces avec une approche TDD
Une application typique suit une architecture en couches, souvent inspirée de modèles tels que MVVM (Model-View-ViewModel) ou Clean Architecture . Chaque couche joue un rôle spécifique dans l’application :
Couche présentation : Fournit les interfaces utilisateur et gère les interactions via des ViewModels .
Les interactions entre ces couches doivent être testées de manière isolée pour s’assurer de leur bon fonctionnement.
Tester ViewModel Android en Présentation
La couche de présentation est responsable de la gestion des interfaces utilisateur (UI) via des ViewModels . Les ViewModels interagissent avec la couche domaine pour obtenir et mettre à jour les données nécessaires à l’interface utilisateur. Dans les tests de la couche présentation, deux aspects doivent être couverts :
Le ViewModel est une classe qui stocke et gère les données relatives à l’interface utilisateur de manière indépendante du cycle de vie des composants UI, comme les Activity et Fragment .
Tester les interactions avec le ViewModel
Pour tester un ViewModel , il est crucial de vérifier comment il interagit avec la couche domaine à travers des use cases et des mappers . Pour simuler ces interactions, nous utilisons des techniques de mocking et de stubbing . Un exemple classique est de moquer un use case et de vérifier si le ViewModel change d’état correctement en fonction de ce use case.
Cette figure présente le processus de test d’un ViewModel dans une architecture en couches. Elle illustre l’utilisation de mocks pour isoler les dépendances externes, comme les Use Cases et les Mappeurs , afin de tester le comportement du ViewModel de manière indépendante.
- À gauche, un Mock Use Case est utilisé pour simuler les interactions de données. Cela permet de tester comment le ViewModel interagit avec les données métier sans avoir à dépendre des implémentations réelles.
- À droite, un Mock Mapper simule la transformation des objets, vérifiant que les données provenant des Use Cases sont correctement converties pour être affichées dans l’interface utilisateur.
Voici un exemple de code pour tester un ViewModel avec un use case simulé :
Ce code définit un test unitaire pour vérifier les interactions entre un ViewModel et un Use Case simulé. La classe FakeUseCase implémente un faux use case qui renvoie des « Données simulées » lorsqu’il est exécuté. Le test ViewModelTest crée une instance de ce faux use case et l’injecte dans le ViewModel via son constructeur. Le test simule ensuite le chargement des données avec la méthode loadData() du ViewModel , et vérifie que l’état du ViewModel ( viewState.data ) contient bien les données simulées renvoyées par le fake use case. Ce test s’assure que le ViewModel interagit correctement avec le Use Case et gère correctement les données reçues.
class FakeUseCase : UseCase {
override fun execute() : Result {
// Simule une sortie réussie
return Result.Success("Données simulées")
}
} class ViewModelTest {
@Test
fun `test ViewModel interactions with use case`() {
// Arrange
val fakeUseCase = FakeUseCase()
val viewModel = MyViewModel(fakeUseCase)
// Act
viewModel.loadData()
// Assert
assertEquals("Données simulées", viewModel.viewState.data)
}
}
Voici le debug dans android studio de la class ViewModelTest :
Cette figure présente l’exécution réussie d’un test unitaire dans l’environnement de débogage. Le test ViewModelTest a passé avec succès, comme indiqué par le message « Tests passed: 1 of 1 test – 9 ms » dans la console. Cela signifie que le test vérifiant les interactions du ViewModel avec le Use Case simulé (comme défini dans le code précédent) s’est exécuté correctement et a produit les résultats attendus.
Tester les états du ViewModel
Le ViewModel expose des états (ou states ) qui peuvent changer en fonction des actions de l’utilisateur ou des résultats obtenus depuis la couche domaine . Tester ces états consiste à vérifier que le ViewModel produit les bons états en fonction des événements simulés.
Cette figure montre la structure d’un projet Android avec une organisation claire des différentes couches. Ici, on voit que le ViewModel , qui appartient à la couche presentation.viewmodel , est responsable de gérer les états de l’interface utilisateur (UI) en fonction des interactions avec l’utilisateur ou des résultats de la couche domaine.
Mocking et Test des Mappers MVVM
Rôle des mappers dans l’application
Les mappers sont des classes qui transforment les objets du domaine en objets utilisables par la couche présentation (souvent des DTO – Data Transfer Objects ou des modèles de vue). Tester les mappers consiste à vérifier que les transformations entre ces deux types d’objets sont correctes.
Cette figure montre l’organisation des tests dans un projet Android, en particulier les tests de la couche data et repository . Ici, nous voyons le test UtilisateurLiveRepositoryTest dans le dossier repository , ainsi que des dossiers pour mapper , ce qui suggère qu’il y a aussi des tests pour les classes de mappage.
Stratégies de test des mappers
Le test des mappers est souvent réalisé en fournissant un objet d’entrée du domaine et en vérifiant que la sortie correspond à ce qui est attendu dans la couche présentation .
Voici un exemple de test d’un mapper :
Ce code Kotlin définit un test unitaire pour vérifier le bon fonctionnement du DomainToPresentationMapper , qui convertit un objet de domaine en un objet adapté à la couche de présentation. Le test commence par initialiser un objet de domaine ( DomainObject ) avec un id et un name . Ensuite, le mapper est utilisé pour transformer cet objet en un PresentationObject . Enfin, le test compare le résultat obtenu avec l’objet de présentation attendu en utilisant assertEquals . Ce test s’assure que le mapper effectue correctement la conversion des données de la couche de domaine vers la couche de présentation, en particulier en vérifiant que l’ id et le name du domaine sont correctement mappés en id et displayName dans la présentation.
class DomainToPresentationMapperTest {
@Test fun `test domain object mapping to presentation object`() {
// Arrange
val domainObject = DomainObject(id = 1, name = "Test") val mapper =
DomainToPresentationMapper()
// Act
val presentationObject =
mapper.map(domainObject)
// Assert
assertEquals(PresentationObject(id = 1, displayName = "Test"),
presentationObject)
}
}
Élément | Description | Code |
---|---|---|
Nom du test | Teste le mappage d’un objet du domaine vers un objet de présentation | fun \test domain object mapping to presentation object`()` |
Objet du domaine | Objet avec un id et un name (données du domaine) | val domainObject = DomainObject(id = 1, name = « Test ») |
Mapper utilisé | DomainToPresentationMapper pour convertir l’objet de domaine | val mapper = DomainToPresentationMapper() |
Objet de présentation | Résultat du mappage, avec un id et un displayName | val presentationObject = mapper.map(domainObject) |
Validation | Vérifie que l’objet mappé correspond à l’objet de présentation attendu | assertEquals(PresentationObject(id = 1, displayName = « Test »), presentationObject) |
Exemples Pratiques en TDD Android
Tests d’un ViewModel avec un use case
Dans cet exemple, nous simulons un use case et testons comment un ViewModel utilise ce use case pour mettre à jour son état.
Ce code Kotlin définit un test unitaire pour vérifier le comportement d’un ViewModel lorsqu’il interagit avec un FakeUseCase (un use case simulé). Le test commence par créer une instance du FakeUseCase , puis l’injecte dans le ViewModel via son constructeur. La méthode loadData() du ViewModel est ensuite appelée pour simuler le chargement des données. Enfin, le test utilise assertEquals pour vérifier que l’état du ViewModel ( viewState.value ) correspond à l’état attendu, ici ViewState.Loaded avec les « Données simulées ». Ce test assure que le ViewModel réagit correctement aux données renvoyées par le FakeUseCase et met à jour son état en conséquence.
@Test fun `test ViewModel with fake use case`(){
// Arrange
val fakeUseCase = FakeUseCase()
val viewModel = MyViewModel(fakeUseCase)
// Act
viewModel.loadData()
// Assert
assertEquals(ViewState.Loaded("Données simulées"),
viewModel.viewState.value)}
La figure montre des méthodes d’observation dans un ViewModel qui sont essentielles pour surveiller les changements d’état continus, tandis que le test simule des interactions avec le ViewModel pour s’assurer que ces changements se produisent comme attendu.
Conclusion sur Test ViewModel Android
Dans ce chapitre, nous avons abordé l’importance des tests dans une architecture propre en utilisant la méthode TDD (Test-Driven Development). Nous avons d’abord déterminé les différentes couches à tester, ce qui est essentiel pour garantir que chaque partie de l’application fonctionne correctement. Ensuite, nous avons examiné les stratégies pour tester efficacement la couche Domaine, la couche Data et la couche Présentation, soulignant l’importance de chaque niveau dans l’assurance qualité. En adoptant ces pratiques, les développeurs peuvent améliorer la fiabilité et la maintenabilité de leurs applications tout en facilitant les mises à jour futures.
Formez-vous gratuitement avec Alphorm !
Maîtrisez les compétences clés en IT grâce à nos formations gratuites et accélérez votre carrière dès aujourd'hui.
FAQ
Comment tester un ViewModel Android ?
Pourquoi utiliser MVVM pour les applications Android ?
Qu'est-ce que le mocking dans le test des ViewModels ?
Comment assurer l'intégrité des données dans un ViewModel ?
Quels sont les avantages de TDD dans le développement Android ?
Conclusion
En appliquant ces méthodes de test, comment pouvez-vous améliorer la qualité et la maintenabilité de vos projets Android tout en assurant une meilleure expérience utilisateur?