Unit Testing Xamarin Forms View Model
Join the DZone community and get the full member experience.Join For Free
View Model in a Nutshell
The view model is the centerpiece of the Model-View-ViewModel pattern. When you're not using MVVM, your presentation logic is in the view (code behind), making harder to test because the logic is coupled to UI elements. On the other hand, when using MVVM, your presentation logic move into the view model, by decoupling logic from the view, you gain the ability to test logic without being bothered by UI elements.
To walk you through this tutorial, I created a Xamarin Forms app called WorkoutTube.
WorkoutTube allows users to
- View a list of workout videos from Youtube.
- Launch the Youtube app with the selected video, if the Youtube app is not installed, it will launch the browser version.
The project can be downloaded here.
The project is already implemented, we will focus on unit tests only.
In order to run the project, edit the file AppConfiguration.cs, under the WorkoutTube project, update the property YoutubeApiKey with your own, you can request Youtube API key here.
To make testing easier, the unit tests project WorkoutTube.UnitTests is using the following packages :
- Autofac: IoC container.
- AutoMock: allows you to automatically create mock dependencies
- AutoFixture: library for .NET designed to minimize the 'Arrange' phase of your unit tests
- FluentAssertions: Fluent API for asserting the results of unit tests
Making the View Model Testable
The HomePageViewModel holds dependencies to other services, instead of relying on the concrete implementation of those services, it relies on their abstractions.
Concrete implementation will be injected through an Ioc container.
Having the ability to inject dependencies is great because when testing we can supply mock objects instead of real ones.
The WorkoutTube project uses AutoFac as Ioc container, dependencies are registered in App.xaml.cs.
Writing Unit Tests
For our tests, the HomePageViewModel will be the subject under the test, we will focus on two types of testing :
- State: checking how the view model's property values are affected by certain actions.
- Interactions: checking that the view model's dependencies service's methods are called properly.
The HomePageViewModel exposes properties and commands to which view HomePage can bind to.
Let's write a test that checks that when the HomePageViewModel is created, Videos property is empty.
We can also write a test to check that when HomePageViewModel is created, SelectedVideo property is null, meaning there is no video selected yet.
How about checking if the OpenVideoCommand is initialized properly.
The HomePageViewModel has a method called Initialize, which is called after the view model is created, in this method, the VideoService fetch videos from Youtube API.
Let's write a test to check the following scenario: after a successful initialization, Videos property should be updated with data retrieved from the service.
Note: notice that we are configuring IVideoService as a mock object, that way we're not communicating with the Youtube API, unit testing is not about calling real API, that's the job of integration testing.
When testing, it is important to not only test the happy path but also the sad path (when things go wrong). In HomePageViewModel, the code that loads the videos is wrapped around a try/catch block, when we catch an exception we display the message by using IDialogService.
Let's write a test for the sad path.
The HomePageViewModel exposes a command called OpenVideoCommand, when executed, it launches the Youtube app through a service called YoutubeServiceLauncher.
Let's write a test that checks that the method OpenAsync of YoutubeServiceLauncher has been called.
We can also write the test for the sad path.
When using MVVM, it is important to unit tests your view models, testing will increase the overall quality of your application.
I hope you enjoy this tutorial, the source code is available for download here. feel free to use it.
Published at DZone with permission of Patrick Tshibanda. See the original article here.
Opinions expressed by DZone contributors are their own.