How to test ViewModel when using Realm Database

I am developing a Xamarin.Forms app. Using following Realm Model in it:

public class MilkManProfile : RealmObject
   {
       [PrimaryKey]
       [MapTo("_id")]
       public ObjectId UserId { get; set; } = ObjectId.GenerateNewId();
       public string Name { get; set; }
       public DateTimeOffset DateOfBirth { get; set; }
       public string Sex { get; set; }
       public string Locality { get; set; }
       public string PhoneNumber { get; set; }
   }

The View Model Code is

realm = Realm.GetInstance();
            MilkManProfile = realm.All<MilkManProfile>().FirstOrDefault();
            if (MilkManProfile == null)
            {
                MilkManProfile = realm.Write(() =>
                {
                    var profile = new MilkManProfile();
                    // set properties if necessary
                    return realm.Add(profile);
                });
            }
public async Task<boolValidateMobileNumber()
        {
            if (Regex.IsMatch(MilkManProfile.PhoneNumber, @"^[0-9]{10}$"))
            {  
                    int l = MilkManProfile.PhoneNumber.Length;
                    for (int i = 1; i < l; i++)
                    {
                        if (MilkManProfile.PhoneNumber[i] != MilkManProfile.PhoneNumber[0])
                        {
                            return true;
                        }
                    }             
            }
            return false;
        }

The Test class in which I need to set the PhoneNumber:

  [Theory]
        [InlineData("23456218973")]//More than 10 digits
        [InlineData("35467")]//Less than 10 digits
        [InlineData("5 67342879")]//One white space
        [InlineData("6666666666")]//All same digits
        [InlineData(")#$^%&*^#@")]//special characters
        [InlineData("anhuoebdog")]//alphabets     

        //Given the Phone number is not valid return false
        async Task IncorrectPhoneNumberShouldReturnFalse(string phoneNumber)
        {
            //Act
            loginViewModel.MilkManProfile.PhoneNumber = phoneNumber;
            bool result = await loginViewModel.ValidateMobileNumber();

            //Assert
            Assert.False(result);
        }

But the test fails with following error:

Message: 
Realms.Exceptions.RealmInvalidTransactionException : Cannot modify managed objects outside of a write transaction.

  Stack Trace: 
NativeException.ThrowIfNecessary(Func`2 overrider)
ObjectHandle.SetValue(IntPtr propertyIndex, RealmValue& value, Realm realm)
RealmObjectBase.SetValue(String propertyName, RealmValue val)
MilkManProfile.set_PhoneNumber(String value) line 21
LoginTest.IncorrectPhoneNumberShouldReturnFalse(String phoneNumber) line 47
--- End of stack trace from previous location ---

I am very new to unit testing and don’t know what would be the best way to test the ViewModel Methods Where I need to set value of the Realm Model.

As the exception says, you need to modify the object in a write transaction. You can read more about the concept in the docs.

If the Realm instance is exposed on the ViewModel, you can use that, or get it from the MilkManProfile:

var realm = loginViewModel.MilkManProfile.Realm;
realm.Write(() =>
{
    loginViewModel.MilkManProfile.PhoneNumber = phoneNumber;
});

Note that this will be technically an integration test, since you’re also involving the database. You might want to instead mock the MilkManProfile property and provide an in-memory object rather than look up one from the database.

1 Like

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.