Mocking Xamarin DependencyService Injection for Unit Tests

How is this even possible? The only way I can see to call DS is via class methods, there is no container I can even register a Mock instance of, constructor injection also seems impossible (these are ViewModels that are injected with services via Autofac)

We Mock all of our services that we use via Autofac quite easily, but since the cross platform ones are "registered" in Xam Forms via Attributes this has suddenly become seemingly very hard.

Any ideas?

Thanks

Posts

  • adamkempadamkemp USInsider, Developer Group Leader mod

    I don't know that answer to your question, but FWIW you don't have to use DependencyService. If there's another dependency injection tool that is more friendly to your testing strategy then you can use that instead.

  • SKallSKall USMember ✭✭✭✭

    Do you have a use case example where you would have to use DependencyService? I would assume you aren't using DependencyService in place of a real DI container in your applications. If you are then I would recommend using something more suitable for the task. AutoFac for PCL works fairly well. I wrote some unit tests for the XLabs.Ioc wrappers and out of those tests Autofac only failed to resolve generic types, for example registering GenericType<> and then resolving with GenericType<int>, which should be fairly rare need for a mobile application.

  • Adam.HillAdam.Hill USMember

    We have an IGrabbaService for the the Grabba barcode readers. We followed the patterns and added an interface in the PCL's , concrete implementation in the iOS project and decorate the implementation class with the atttribute and everything has workd well, until we started writing unit tests.

    When I use Autofac (which we already use for many other services) to register via 'builder.RegisterType().As();' it will not compile because the Autofac configs (Bootstrapper & the Module for our specific app) live in the PCL's as well. If I try to use .Self(), Autofac blows up when trying to resolve the type.

    I don't see a way around this, the concrete type lives in the iOS project and the PCL's have no knowledge of these (and shouldn't)

    Thanks.

  • SKallSKall USMember ✭✭✭✭

    Matt Whetton wrote a detailed article on how to use the XLabs.Ioc abstraction I have written. It's a fairly flexible library as far as how you set up the container and a static Resolver class acts as the wrapper for any of the containers. Autofac is included as one of the plugins and it does work.

    http://www.codenutz.com/autofac-ninject-tinyioc-unity-with-xamarin-forms-labs-xlabs/

    It's available through NuGet but you could also get the source code which has a unit test solution and tests different containers: https://github.com/XLabs/Xamarin-Forms-Labs

    Your post made me also realize a design flaw in the Resolver that I just fixed in the latest code (Nuget should follow shortly).

  • ylemsoulylemsoul RUMember ✭✭✭
    edited September 2015

    In @SKall's reference important this:

    The Autofac package is called XLabs.IoC.Autofac and needs to be installed on all platform specific projects

    @Adam.Hill, so you either move your composition root to platform specific projects or may be better alternative is to use shared project for it.
    Or, you still can use IDependencyService in PCL project where you re-register your dependency in custom IoC:
    (example with Microsoft Unity)
    container.RegisterType<IMediaPicker>( new TransientLifetimeManager(), new InjectionFactory(_ => DependencyService.Get<IMediaPicker>(DependencyFetchTarget.NewInstance)));

Sign In or Register to comment.