Unit Testing in Xamarin with NUnit

Unit Testing in Xamarin with NUnit

Introduction

Today when working in an agile development project, the stakeholders usually wants us to deliver features rapidly and frequently. We also need to ensure a high quality level of the released features and be able to safely refactor the code base due to changed requirements.

This makes it impossible to rely only on manual testing, and we need to automate as much testing as possible.

One type of automated testing is the unit test, where we isolate one unit (module/class) at a time, and test that it behaves as aspected. Sounds simple right!

There are a lot of tools and frameworks available to make it easy to configure, mock and unit test out there. In this article we will have a quick look at NUnit, NSubstitute and Autofac.

We at Avalon Innovation are more than 250 specialists all over Scandinavia who are passionate about developing ground-breaking, innovative product and system solutions that really make a difference. Since 1997 we have tackled many challenging and difficult assignments, which have provided us with broad technical expertise and unique insights into innovation.

The Demo Project

Download the demo project from my GitHub for the complete source code from this article.

Dependency Injection

When we want to test a single unit we often need to remove or replace that units dependencies. This is called mocking! We replace the dependencies with something else that behaves in a predictive way.

Dependency injection or Inversion of Control (IoC) is an architectural pattern where a units dependencies are provided to the unit instead of being created inside the unit.

Lets look at an example!

    public interface IProfileService
    {
        Profile GetProfile();
    }

    public class ProfileService : IProfileService
    {
        private readonly IProfileRepository _profileRepository;

        public ProfileService(IProfileRepository profileRepository)
        {
            _profileRepository = profileRepository;
        }

        public Profile GetProfile()
        {
            return _profileRepository?.GetProfile();
        }
    }

In the example above the class ProfileService is dependent on the interface IProfileRepository, and that gets injected to the constructor. This is called constructor injection and is a common way to do dependency injection.

This is really great because now ProfileService is only aware of IProfileRepository and not with the exact implementation! In production it will probably be implemented with a class that fetches and saves profile information to a database or a web service, but in a unit test scenario we can send a mocked implementation of IProfileRepository to ProfileService to isolate it from its dependency!

In this article I will use Autofac for the configuration of dependencies. A tool is perhaps not necessary, but it makes our job a bit easier.

Testing a simple unit

The demo project has a class called Profile that contains both data about a users profile and some calculations of daily recommended energy, carb, fat and protein intake. These calculations are perfect for unit testing!

The Profile class does not have any external dependencies that we need to mock, we just need to create and instance, add some data, run the calculations and validate the results.

    [TestFixture]
    public class TestProfileCalculations
    {
        private Profile _maleProfile;

        [SetUp]
        public void SetUp()
        {
            _maleProfile = new Profile
            {
                BirthDate = DateTime.Now.AddYears(-47),
                Gender = GenderTypes.Male,
                Weight = 105,
                Height = 183,
                PhysicalActivity = PhysicalActivityTypes.Moderate
            };
        }

        [Test]
        public void TestCalculateDailyEnergyIntakeMale()
        {
            // ARRANGE

            // ACT
            var result = (int)Math.Round(_maleProfile.CalculateDailyEnergyIntake());

            // ASSERT
            Assert.AreEqual(3268, result);
        }
    }

Lets create a class called TestProfileCalculations! First we need to mark it with [TestFixture] for NUnit to find it. Then we create a new instance of the Profile class in the method marked with [SetUp].

Finally we create a test method. In this case we want to test that the calculated daily energy intake for this profile is 3268 kcal. We know that this is the correct value and we want to test that the calculations are correct.

A unit test usually consists of three steps. Arrange data before the test, act on the subject under test and assert that the results of the test is what we expected.

In this case we don't need to arrange any more, we have the created profile. Instead we call the method and assert that the returned value is equal to 3268 kcal. Done!

Mocking dependencies

In the demo project we have a class called ShowProfileViewModel that calls a couple of methods in IProfileService to load and save a users profile. We need to write a test to ensure that this is done in a correct way!

    public interface IShowProfileViewModel
    {
        Profile CurrentProfile { get; }

        void LoadProfile();
        void SaveProfile();
    }

    public class ShowProfileViewModel : IShowProfileViewModel
    {
        private readonly IProfileService _profileService;

        public ShowProfileViewModel(IProfileService profileService)
        {
            _profileService = profileService;
        }

        public Profile CurrentProfile { getprivate set; }

        public void LoadProfile()
        {
            if (_profileService.HasProfile() == false)
            {
                CurrentProfile = new Profile();
                return;
            }

            CurrentProfile = _profileService.GetProfile();
        }

        public void SaveProfile()
        {
            _profileService.SaveProfile(CurrentProfile);
        }
    }

There are some logic here.

When LoadProfile() is called and a profile is missing, a new one is created and the loaded or created profile is then accessible with the property CurrentProfile.

When SaveProfile() is called the data in CurrentProfile is sent to IProfileService for processing.

Lets write some tests!

        private IProfileRepository _profileRepository;
        private IProfileService _profileService;
        private IShowProfileViewModel _subject;

First we create some variables! One for the subject and then one for IProfileService and one for IProfileRepository.

        [SetUp]
        public void SetUp()
        {
            // Create the builder
            var builder = new ContainerBuilder();

            // Register a mock instance for IProfileRepository
            _profileRepository = Substitute.For<IProfileRepository>();
            builder.RegisterInstance(_profileRepository)?.As<IProfileRepository>()?.SingleInstance();

            // Register a mock instance for IProfileService
            _profileService = Substitute.For<IProfileService>();
            builder.RegisterInstance(_profileService)?.As<IProfileService>()?.SingleInstance();

            // Register the subject
            builder.RegisterType<ShowProfileViewModel>()?.As<IShowProfileViewModel>()?.SingleInstance();

            // Build the IoC container
            var container = builder.Build();

            // Resolve the subject instance
            _subject = container.Resolve<IShowProfileViewModel>();
       }

Then we setup the tests in a number of steps.

  1. We create a ContainerBuilder with Autofac to register our types in
  2. We use NSubstitute to create a mock object from IProfileRepository and add that to Autofac. NSubstitute makes it easy for us to configure in runtime how the mock objects behave.
  3. We use NSubstitute to create a mock object from IProfileService and add that to Autofac as well.
  4. We register the subject in Autofac with its normal implementation, because that is what we want to test.
  5. After the registration of types is done, we resolve the subject instance.

Now we have an instance of the test subject (ShowProfileViewModel) and mocked instances of IProfileRepository and IProfileService. When the new instance of ShowProfileViewModel is created Autofac will automatically inject the mocked instance of IProfileService to its constructor.

        [Test]
        public void TestLoadProfileWithEmptyProfile()
        {
            // ARRANGE
            _profileService.HasProfile().Returns(false);

            // ACT
            _subject.LoadProfile();

            // ASSERT
            Assert.NotNull(_subject.CurrentProfile);

            Assert.AreEqual(Profile.DefaultGender(), _subject.CurrentProfile.Gender);
            Assert.AreEqual(Profile.DefaultBirthDate(), _subject.CurrentProfile.BirthDate);
            Assert.AreEqual(Profile.DefaultPhysicalActivity(), _subject.CurrentProfile.PhysicalActivity);
            Assert.AreEqual(0_subject.CurrentProfile.Weight);
            Assert.AreEqual(0_subject.CurrentProfile.Height);
        }

Lets test that ShowProfileViewModel behaves correctly when we call LoadProfile().

We start with configuring that the method HasProfile() in IProfileService should always return false. This is one of the nice things that NSubstitute gives us! The ability to change mocked objects behavior easily.

Then we act on the test subject and call the method LoadProfile().

Now because a profile does not exist ShowProfileViewModel will create a new instance of Profile, right? This we can assert!

        [Test]
        public void TestLoadProfileWithExistingProfile()
        {
            // ARRANGE
            var profile = new Profile
            {
                BirthDate = DateTime.Now.AddYears(-45),
                Gender = GenderTypes.Male,
                Weight = 100,
                Height = 183,
                PhysicalActivity = PhysicalActivityTypes.Moderate
            };

            _profileService.HasProfile().Returns(true);
            _profileService.GetProfile().Returns(profile);


            // ACT
            _subject.LoadProfile();

            // ASSERT
            Assert.NotNull(_subject.CurrentProfile);

            Assert.AreEqual(profile.Gender, _subject.CurrentProfile.Gender);
            Assert.AreEqual(profile.BirthDate, _subject.CurrentProfile.BirthDate);
            Assert.AreEqual(profile.PhysicalActivity, _subject.CurrentProfile.PhysicalActivity);
            Assert.AreEqual(profile.Weight, _subject.CurrentProfile.Weight);
            Assert.AreEqual(profile.Height, _subject.CurrentProfile.Height);
            Assert.AreEqual(profile.Age, _subject.CurrentProfile.Age);
            Assert.AreEqual(45, _subject.CurrentProfile.Age);
        }

Now we can continue to write a test for when LoadProfile() is called and a profile exists. HasProfile() should return true and GetProfile() should return a known profile so we can assert that the correct profile is added to ShowProfileViewModel. Done!

For more examples please look at the demo project on GitHub!

Conclusions

Unit testing is necessary to deliver features frequently while ensuring a high quality of the delivered product. Unit tests are easy to write if we use an architecture that enables us to mock dependencies and isolate the units that needs to be tested.

More info on the frameworks used in this article can be found online:

https://nunit.org/

https://nsubstitute.github.io/

https://autofac.org/

Happy testing!

To view or add a comment, sign in

More articles by Jonas Frid

  • We need to stop pretending that everyone is needed at work

    We are facing a transformation greater than industrialization. Yet we still talk as if work is the only way to earn a…

    5 Comments
  • Är 2026 det sista året vi byggde UI?

    Det finns en anledning till att det här är svårt att greppa. Vi har byggt mjukvara på samma sätt i över 40 år: System…

  • Take your App to the next Step with Microsoft App Center

    Introduction In this article I will give you an introduction on how to use Microsoft App Center to manage everything…

  • An Introduction to Microsoft Azure DevOps

    Introduction In this article I will give you an introduction to DevOps and how to use Microsoft Azure DevOps to build…

    2 Comments
  • Unit Testing in Android Studio with Kotlin and JUnit

    Introduction Today when working in an agile development project, the stakeholders usually wants us to deliver features…

  • Custom hit test in Xamarin.iOS

    Views can catch touch events, but normally that is done in a rectangle! What if you want a round image and only capture…

  • MvvmMobile! Just another MVVM framework? ;-)

    Introduction MvvmMobile is an MVVM framework specifically developed for Xamarin iOS and Xamarin Android with focus on…

  • Range Slider In Xamarin Forms

    Intro Earlier this year I found myself in need of a range slider for a Xamarin Forms project. I found a couple of…

    1 Comment
  • Bindable Grid In Xamarin Forms

    Intro Xamarin Forms is a great platform for building native cross-platform apps for iOS, Android and Windows, but…

    5 Comments

Others also viewed

Explore content categories