AndriiGenesis
AndriiGenesis

Reputation: 11

Mock static method with Context as parameter using PowerMockito

I have class with static method

public class GrandUtils {
 
    /**
     * Return list of existing user's emails
     *
     * @param c context of the app
     * @return list of existing accounts in system or empty list
     */
    public static Set<String> getAccountsList(Context c) {
        Set<String> accountsList = new HashSet<>();
        Pattern emailPattern = Patterns.EMAIL_ADDRESS; // API level 8+
        Account[] accounts = AccountManager.get(c).getAccounts();
        for (Account account : accounts) {
            if (emailPattern.matcher(account.name).matches()) {
                accountsList.add(account.name);
            }
        }
        return accountsList;
    }
}

In addition I've implemented complicated IntentService which calls GrandUtils.getAccountList(Context c) and save this accounts to SharedPreferences. So I want to mock method with my own set of emails and then check with result saved in SharedPreferences

So I wrote this test

    @RunWith(MockitoJUnitRunner.class)
    @PrepareForTest(GrandUtils.class)
    public class CampaingTrackingTest extends ApplicationTestCase<Application> {
        
            public CampaingTrackingTest() {
                super(Application.class);
            }
        
            @Override
            @Before
            public void setUp() throws Exception {
                super.setUp();
                System.setProperty("dexmaker.dexcache", getContext().getCacheDir().getPath());
                createApplication();
            }
        
            @MediumTest
            public void testMockAccounts() {
                HashSet<String> mails = new HashSet<>();
                mails.add("[email protected]");
                //it needs Context
PowerMockito.when(GrandUtils.getAccountsList(getContext())).thenReturn(mails);
        
                Set<String> givenMails = GrandUtils.getAccountsList(getContext());
                assertNotNull(givenMails);
                assertEquals(givenMails.size(), 1);
        
                // Next part for comparing data with IntentService and SharedPreferences
            }
        }

but it fails with

org.mockito.exceptions.misusing.MissingMethodInvocationException: when() requires an argument which has to be 'a method call on a mock'. For example: when(mock.getArticles()).thenReturn(articles);

Also, this error might show up because:

  1. you stub either of: final/private/equals()/hashCode() methods. Those methods cannot be stubbed/verified. Mocking methods declared on non-public parent classes is not supported.

  2. inside when() you don't call method on mock but on some other object.

I'm sure that I'm doing something wrong, but what?

Upvotes: 0

Views: 2250

Answers (1)

Daniel Zolnai
Daniel Zolnai

Reputation: 16910

See this PowerMock example for the mocking of the static method Log.d(String tag, String message):

https://github.com/mttkay/droid-fu/blob/master/src/test/java/com/github/droidfu/TestBase.java

I think it gives a good example for dealing with static methods.

Upvotes: 1

Related Questions