2

So I have a class that takes in a Context through the constructor, and grabs the default SharedPreferences from it using:

PreferenceManager.getDefaultSharedPreferences(context)

I'm testing this class, and in my unit test I've written the following code to retrieve a mocked SharedPreferences instance when getSharedPreferences(String, int) is invoked:

Context context = mock(Context.class);
SharedPreferences sharedPreferences = mock(SharedPreferences.class);

when(context.getSharedPreferences(anyString(), anyInt()))
            .thenReturn(sharedPreferences);
when(sharedPreferences.getString(anyString(), nullable(String.class)))
            .thenReturn(tokenManager.getToken());

When I run the test for this class, it ends up with a null object instead of my mocked SharedPreferences instance. However, if I grab the SharedPreferences instance with context.getSharedPreferences("stubbed", 123), I end up with my mocked SharedPreferences code.

So why does PreferenceManager.getDefaultSharedPreferences(context) return null instance while directly calling getSharedPreferences on my mock Context returns my mocked SharedPreferences instance?

Jonathan Chiou
  • 349
  • 6
  • 15
  • did you check the code of `PreferenceManager.getDefaultSharedPreferences(context)`? How does the PM get the data from the `context`? – P.J.Meisch Nov 17 '18 at 16:54
  • `return context.getSharedPreferences(getDefaultSharedPreferencesName(context), getDefaultSharedPreferencesMode());`` – Jonathan Chiou Nov 19 '18 at 17:03

2 Answers2

0

Based on this document (https://developer.android.com/training/testing/unit-testing/local-unit-tests) and debugging the code line by line, the conclusion I've reached about why this occurs is because the android code used for unit tests in gradle is actually just a shell that returns stubbed values on every method invocation, so naturally that leads me to assume that the code for PreferenceManager.getDefaultSharedPreferences() that's being used in my unit tests is more or less return null.

Jonathan Chiou
  • 349
  • 6
  • 15
0

So you need to mock the static call to PreferenceManager.getDefaultSharedPreferences(context). This is not possible at the moment with mockito, there is still discussion going on the corresponding issue.

One solution is shown in the accepted answer of this question, you could check PowerMock or JMockit as alternatives

P.J.Meisch
  • 18,013
  • 6
  • 50
  • 66