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