Reputation: 217
[UPDATE]:
I know what NPE is,but I don't know why it appears here.So I think this is totally not a duplicated question as What is a Null Pointer Exception, and how do I fix it?.But any way I have found the answer.To use Mockito in instrumented test,addition dependencies dexmaker and dexmaker-mockito are also required:
androidTestCompile "com.google.dexmaker:dexmaker:1.2"
androidTestCompile "com.google.dexmaker:dexmaker-mockito:1.2"
And if you don't run yout test under MockitoJUnitRunner
,addition initialization is also required as below answer has mentioned:
MockitoAnnotations.initMocks(this);
See also Initialising mock objects - MockIto for futher discussion.
I want to write a simple test that checks if user's data is shown on the UI.The Activity retrieves the data stored in sharedPreferences within onResume() and shows it on the UI.The following is my code for the test:
@RunWith(AndroidJUnit4.class)
public class EditProfileActivityTest {
@Mock
private UserPreference userPreference;
private String FAKE_NAME = "Test";
@Rule
public ActivityTestRule<EditProfileActivity> activityTestRule = new ActivityTestRule(EditProfileActivity.class,true,false);
@Before
public void setUp(){
//Set fake SharedPreferences
when(userPreference.getName()).thenReturn(FAKE_NAME);
//Start Activity
Intent intent = new Intent();
activityTestRule.launchActivity(intent);
}
@Test
public void showUserData() throws Exception{
onView(withId(R.id.name_tv)).check(matches(withText(FAKE_NAME)));
}
}
where UserPreference is a custom class which simply wraps SharedPreference class and contains lots of getters and setters.This is its constructor
public UserPreference(Context context) {
this.context = context;
sharedPreferences = this.context.getSharedPreferences("Pref", Context.MODE_PRIVATE);
prefEditor = sharedPreferences.edit();
}
and one of its getter
public String getName() {
return sharedPreferences.getString(context.getString(R.string.pref_name), "Guest");
}
But when I run the test,it keeps showing NullPointerExceptiions on this line
when(userPreference.getName()).thenReturn(FAKE_NAME);
I've searched for related topics but I still can't see why.I think the concept of mock is to re-define a method's behavior no matter what the real implementation is. I am new to testing,so I am sorry in advance if this is a silly qustion.
By the way the test runs perfectly with the following code
@RunWith(AndroidJUnit4.class)
public class EditProfileActivityTest {
private UserPreference userPreference;
private String FAKE_NAME = "Test";
@Rule
public ActivityTestRule<EditProfileActivity> activityTestRule = new ActivityTestRule(EditProfileActivity.class,true,false);
@Before
public void setUp(){
//Start Activity
Intent intent = new Intent();
activityTestRule.launchActivity(intent);
}
@Test
public void showUserData() throws Exception{
onView(withId(R.id.name_tv)).check(matches(withText(FAKE_NAME)));
}
}
But the preference data it retrieves is from the "real" device.In this case i can't make an assertion about what will be displayed so I can't tell whether the test is passed.This is why I want to mock the preference to make it predictable.
Upvotes: 1
Views: 2703
Reputation: 15064
You have to init your mocks in @Before
like so:
public void setUp() {
MockitoAnnotations.initMocks(this);
// ...
}
Upvotes: 4
Reputation: 9334
Your userPreference object is null, but you're trying to call a method on it. If you post all of your code it will be easier.
The idea of a Mock object is correct - but you're not using a Mock object, you're calling when() on a real object, but which hasn't been created yet, thus the NPE.
Upvotes: -1