Unit testing Android components inside Xamarin application

Boyd, Casey 1 Reputation point
2021-03-16T16:11:00.277+00:00

We have a Xamarin Android application which I am trying to add better unit testing around. We are using SimpleInjector for our DI and NUnit/Moq for our test running and mocking framework. I've done very similar work in the past with a native Android app using Mockito/Robolectric and Dagger for DI and everything was pretty seamless once you got it configured correctly.

I am trying to produce a similar level of testing to that previous project and it is proving mighty challenging. The mocking frameworks for C# and Xamarin seem to rely on having interfaces or abstract classes to mock rather than concrete implementations, and they have further issues when the classes do not have a parameterless constructor. Mockito did not have this same limitation, and there wasn't JNI in the middle to mess with the class reflection the mocking library has to do to build the object. It does not appear that you are able to Mock concrete Android classes due to the above and if you can, the documentation is mostly absent. Has anyone solved this issue or know tricks that I'm not aware of?

For example:

We are extending the Android class Android.OS.CountDownTimer and contstructor-injecting a factory which creates a new timer object for us with the constructor args (long millisInFuture, long countDownInterval). Simple enough to implement. I'd like to test that the Factory.Create() method and the Timer.Start() method get called inside of our OnStart() fragment method.

In a test class,

var countDownTimerFactory = new Mock<ITimerFactory>(); //This returns our concrete class through DI

var mockTimer = new Mock<CountDownTimer>(MockBehavior.Default, new object[] { _WAIT_TIME_MS, _COUNTDOWN_INTERVAL_MS });
// Those values are 2000 and 1000. 
// If you try building this mock without the constructor args you get the parameterless constructor error

countDownTimerFactory.Setup(factory => factory.Create(It.IsAny<long>(), It.IsAny<long>())).Returns(mockTimer.Object);

OurFragment subject = new OurFragment(countDownTimerFactory.Object);

countDownTimerFactory.Verify(x => x.Create(_WAIT_TIME_MS, _COUNTDOWN_INTERVAL_MS));
mockTimer.Verify(x => x.Start());

This code will blow up because it can't find the proxy class on the dexpath. stacktrace

Verified that our timer class constructor does get called during the test and blows up somewhere in the base call.

public OurTimer (long millisInFuture, long countDownInterval) : base(millisInFuture, countDownInterval)
{
}

This is just for the CountDownTimer class but pick pretty much any Android class and you'll run into the same issues. Am I just missing something core to Xamarin Android dev which I'm supposed to understand and there is no documentation around, or is this an unsolved problem and people just don't unit test at this level in Xamarin?

Thanks!

PS - I posted this same question on stackoverflow and haven't received any responses yet (https://stackoverflow.com/questions/66574864/unit-testing-android-components-inside-xamarin-application)

Visual Studio Testing
Visual Studio Testing
Visual Studio: A family of Microsoft suites of integrated development tools for building applications for Windows, the web and mobile devices.Testing: The act or process of applying tests as a means of analysis or diagnosis.
337 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Ken Tucker 5,846 Reputation points
    2021-04-06T00:26:56.203+00:00

    Here are some other mocking libraries I like. The free Fake It easy

    https://fakeiteasy.github.io/

    or some paid products like TypeMock Isolator or justmock

    0 comments No comments