I am trying to unit test Realm and its interactions but things are not going too well. I have included all dependencies and keep getting vague failures, below is my code for the Helper
class which is a wrapper over Realm
.
Questions
Is this the correct way of testing Realm?
How can I test data that is in the app's sandbox, can that data only be tested by UI/Instrumentation tests?
I am getting an error currently (below) and before I was getting a "Powermock zero args constructor doesn't exist"
Below is the current code I have for my Unit test:
@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(RobolectricTestRunner.class)
@Config(constants = BuildConfig.class, sdk = 21, application = CustomApplicationTest.class)
@PowerMockIgnore({"org.mockito.*", "org.robolectric.*", "android.*", "javax.crypto.","java.security.*"})
@SuppressStaticInitializationFor("io.realm.internal.Util")
@PrepareForTest({Realm.class, RealmConfiguration.class,
RealmQuery.class, RealmResults.class, RealmCore.class, RealmLog.class})
public class DatabaseHelperTest {
@Rule
public PowerMockRule rule = new PowerMockRule();
private DatabaseHelper dB;
private Realm realmMock;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mockStatic(Realm.class);
mockStatic(RealmConfiguration.class);
mockStatic(RealmCore.class);
mock(DatabaseHelper.class);
final Realm mockRealm = PowerMockito.mock(Realm.class);
realmMock = mockRealm;
final RealmConfiguration mockRealmConfig = PowerMockito.mock(RealmConfiguration.class);
doNothing().when(RealmCore.class);
RealmCore.loadLibrary(any(Context.class));
whenNew(RealmConfiguration.class).withAnyArguments().thenReturn(mockRealmConfig);
when(Realm.getInstance(any(RealmConfiguration.class))).thenReturn(mockRealm);
when(Realm.getDefaultInstance()).thenReturn(mockRealm);
when(Realm.getDefaultInstance()).thenReturn(realmMock);
when(realmMock.createObject(Person.class)).thenReturn(new Person());
Person person = new Person();
person.setId("2");
person.setName("Jerry");
person.setAge("25");
Person person2 = new Person();
person.setId("3");
person.setName("Tom");
person.setAge("22");
List<Person> personsList = new ArrayList<>();
personsList.add(person);
personsList.add(person2);
RealmQuery<Person> personRealmQuery = mockRealmQuery();
when(realmMock.where(Person.class)).thenReturn(personRealmQuery);
RealmResults<Person> personRealmResults = mockRealmResults();
when(realmMock.where(Person.class).findAll()).thenReturn(personRealmResults);
when(personRealmResults.iterator()).thenReturn(personsList.iterator());
when(personRealmResults.size()).thenReturn(personsList.size());
when(realmMock.copyFromRealm(personRealmResults)).thenReturn(personsList);
realmMock = mockRealm;
dB = new DatabaseHelper(realmMock);
}
@Test
public void insertingPerson(){
doCallRealMethod().when(realmMock).executeTransaction(any(Realm.Transaction.class));
Person person = mock(Person.class);
when(realmMock.createObject(Person.class)).thenReturn(person);
dB.putPersonData();
verify(realmMock, times(1)).createObject(Person.class);
verify(person, times(1)).setId(anyString());
}
@Test
public void testExistingData(){
List<Person> personList = dB.getPersonList();
//NPE if checking person object properties i.e name, id. Only list size is available why?
Assert.assertEquals(2, personList.size());
}
@SuppressWarnings("unchecked")
private <T extends RealmObject> RealmQuery<T> mockRealmQuery() {
return mock(RealmQuery.class);
}
@SuppressWarnings("unchecked")
private <T extends RealmObject> RealmResults<T> mockRealmResults() {
return mock(RealmResults.class);
}
Error:
org.mockito.exceptions.misusing.NotAMockException:
Argument passed to verify() is of type Realm$$EnhancerByMockitoWithCGLIB$$317bc746 and is not a mock!
Make sure you place the parenthesis correctly!
See the examples of correct verifications:
verify(mock).someMethod();
verify(mock, times(10)).someMethod();
verify(mock, atLeastOnce()).someMethod();
at com.appstronomy.realmunittesting.db.DatabaseHelperTest.insertingPerson(DatabaseHelperTest.java:133)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)