简体   繁体   中英

Mockito/Realm (when-then): how to pass arguments from method to its submethod

Trying to unit test a project that uses Realm. I stubbed realm methods to just test my own code and found a problem with RealmQuery. I want to test whether an object is (1) added to the Realm db; (2) can be retrieved; (3) if that object's set attribute matches what I expect. Here are parts of my setup() and Test.

How I stub a realm database (someList is global & List<>) in setup()

SomeRealmObject some1;
some1.setId(1);
some1.setName("some1");

SomeRealmObject some2;
some2.setId(2);
some2.setName("some2");

someList = new ArrayList<SomeRealmObject>();
someList.add(some1);
someList.add(some2);

How I stub copying to Realm (add function) in setup()

when(mockRealm.copyToRealm).then(new Answer() {
        @Override
        public Object answer(InvocationOnMock invocation) throws Throwable {

            Object[] args = invocation.getArguments();

            SomeRealmObject some = (SomeRealmObject) args[0];

            userList.add(user);

            return user;
        }
    });

How I stub RealmQuery (search function) in setup()

RealmQuery someRealmQuery = someRealmQuery(); //followed mockito example on github

when(mockRealm.where(SomeRealmObject.class)).thenReturn(someRealmQuery);
when(realmQuery.equalsTo(anyString, anyInt).thenReturn(someRealmQuery);
when(realmQuery.findFirst()).then(findFirstAnswer);

Problem starts here. I need realmQuery.equalsTo(...) to pass its arguments to the next method in the chain. I think it necessary (but I may be wrong) because I should test two methods that follow: findFirst() and findAll(). Any Ideas?

How I stub findFirst() in setup()

Answer findFirstAnswer = new Answer(){

    @Override
    public Object answer(InvocationOnMock invocation) throws Throwable {

        Object[] args = invocation.getArguments();

        String key = args[0].toString(); //Let's just use an Id search for 
        int id = (int) args[1];          //an example.

        for(int count = 0; someList.get(count) != null; count++){

            if(someList.get(count).getId == id){
            return someList.get(count);
        }

        return null; //test will fail, someRealmObject not found
    }
}

How I unit test my createSomeObject (eg createAccount)

@Test
public void create_someObj_test() {

    String expectedReturnedName = "someName";
    String actualReturnedName;

    SomeRepositoryImpl manager; //Class with business logic (mvp pattern) 
    SomeRepositoryImpl.initialize();
    manager = someRepositoryImpl.getInstance(); 

    SomeRealmObject some = new SomeRealmObject();
    some.setID(6);
    some.setName(expectedReturnedName);

    //mock adding user to realm, should actually add it to a list
    mockRealm.beginTransaction();
    mockRealm.copyToRealm(some);
    mockRealm.commitTransaction();

    actualReturnedName = mockRealm.where(SomeRealmObject.class).equalTo("id", some.getId()).findFirst().getName().toString(); 

    //PASS if object exists and name matches
    //FAIL if name does not match
    //FAIL if nullPointerException because no match/object not found
    assertEquals(expectedReturnedName, actualReturnedName );
}

This is not a direct answer to your question. A direct answer would involve a discussion of what findFirstAnswer is and what its name property contains.

Instead, though, I would ask: "what are you trying to test"? This is not quite a test of the Realm DB library (a good thing). It looks to me almost like a test of Mockito! If the test succeeds, you will know that Mockito Mocks can return an object with a certain name.

It is common practice to wrap a data layer in a very thin API, something like the Data Access Objects popular with Spring and the like. If you can mock the data API, you can test the heck out of your business layer. If your data API needs testing, you can also test things like "does this API call get translated into the proper query?" or "does the API crash if the result is empty?".

Sorry for the oblique answer but I think if you revisit the question of what you are trying to test, this entire problem might evaporate.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM