Unit Testing View Models that use Xamarin Plugin(s)

Xamarin Plugins provide a wide range of cross-platform functionality libraries. The platform-specific functionality is implemented on the supported platforms and it can be accessed through the common API in the abstraction layer. In Xamarin Forms, view models consume the PlugIn API from the abstraction layer and implementation of the plugin is in the platform-specific layer. The PlugIn invokes the implementation using bait and switch instead of IOC.
Unit testing view model requires either the implementation of the abstraction layer or mocking it. Bait and Switch technique makes it harder to mock in unit testing. This article explains how to unit test a view model that has the dependency on Xamarin PlugIn(s).
One way to do it would be to create a wrapper for each plugin and use the desired Plugin from the wrapper. In the unit test, replaces the wrapped plugin with a mock.
The other way would be to create a Plugin provider interface that provides access to one or more plugins. IOC is used to access the provider and effectively the plugins inside it. The behavior of the provider can be changed based on if it is used in the app or in the view model.

The provider paradigm provides two advantages over the wrapper approach.
1. There is only one provider for all plugins. So, the developer need not create one wrapper per plugin. Effectively there is less overhead in the App when there is more than one plug-in.
2. This framework provides loose coupling compared to the wrapper that has tight coupling. This takes the App closer to the SOLID principles.

Here is how a “plugin provider” would look like.

///
/// Interface to provide plugin.
/// This can be mocked in the unit tests
/// 

public interface IPlugInProvider
{
///
/// Plugin for secure storage
/// 
ISecureStorage SecureStorage { get; }
}

In the App, the default implementation of the plugin provider is implemented in the common layer and it uses real plugins.

///
/// Provider for plugin
/// 
public class PlugInProvider : IPlugInProvider
{
///
/// SecureStorage plugin
/// 

/// Not sure how to fix this > in the wordpress.
public ISecureStorage SecureStorage => CrossSecureStorage.Current;
}

The provider would be registered using IOC. View Model would access the PlugIn through the provider interface using DependencyService.

// get the secure storage
_secureStorage = DependencyService.Get().SecureStorage;

In the UnitTest, the implementation of IPlugInProvider would be a mock implementation that provides access to mock PlugIn.

///
/// This is a provider for one or more plugins
/// 
public class PluginProviderMock : IPlugInProvider
{
#region IPlugInProvider implementation
///
/// Secure storage
/// 

/// Not sure how to fix this > in the wordpress
public ISecureStorage SecureStorage => _secureStorageMock;
#endregion

private SecureStorageMock _secureStorageMock = new SecureStorageMock();
}

With this paradigm, one can mock and change the behavior of the PlugIn implementation in UnitTest with SOLID principles. It can help in generating test scenarios that will make the App more robust.

Code:

https://github.com/sameerkapps/SecureStorage/tree/master/SecureStorageSample

Published by: Sameer Khandekar

I am a passionate software engineer who loves to work on Azure microservices, REST API, SDKs, and .NET apps using WPF, Xamarin, and MAUI. The work includes highly scalable geo-distributed services and an authentication library with nearly 500 million downloads. I also had fun integrating with hardware using Bluetooth (BLE). More here: https://www.sameer.blog/about/

Categories UncategorizedLeave a comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s