为什么它一直在模拟对象上投掷NPE

时间:2015-11-16 16:18:45

标签: java android testing nullpointerexception mockito

[更新]

我知道NPE是什么,但我不知道为什么会出现在这里。所以我认为这完全不是一个重复的问题What is a Null Pointer Exception, and how do I fix it? 。但是我发现的任何方式答案。要在仪器化测试中使用Mockito,还需要添加依赖项dexmaker和dexmaker-mockito:

androidTestCompile "com.google.dexmaker:dexmaker:1.2"
androidTestCompile "com.google.dexmaker:dexmaker-mockito:1.2"

如果您未在MockitoJUnitRunner下运行测试,则还需要进行额外初始化,如下面的答案所述:

MockitoAnnotations.initMocks(this);

另见Initialising mock objects - MockIto进一步讨论。

我想编写一个简单的测试来检查用户的数据是否显示在UI上.Activity检索存储在onResume()内的sharedPreferences中的数据并在UI上显示。以下是我的测试代码:< / p>

@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)));
}
}  

其中UserPreference是一个自定义类,它只包装SharedPreference类并包含许多getter和setter。这是它的构造函数

 
public UserPreference(Context context) {
    this.context = context;
    sharedPreferences = this.context.getSharedPreferences("Pref", Context.MODE_PRIVATE);
    prefEditor = sharedPreferences.edit();
}  

和其中一个吸气剂

 
public String getName() {
    return sharedPreferences.getString(context.getString(R.string.pref_name), "Guest");
}  

但是当我运行测试时,它会在此行上显示NullPointerExceptiions

 
when(userPreference.getName()).thenReturn(FAKE_NAME);

我搜索了相关的主题,但我仍然看不出原因。我认为模拟的概念是重新定义方法的行为,无论真正的实现是什么。我是新来测试的,所以如果这是一个愚蠢的问题,我很抱歉。

顺便说一下,测试与以下代码完美匹配

@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)));
    }
}

但它检索的偏好数据来自“真实”设备。在这种情况下,我不能断言将要显示什么,所以我无法判断测试是否通过。这就是我想要的原因嘲笑偏好使其可预测。

2 个答案:

答案 0 :(得分:3)

你必须像@Before一样初始化你的模拟:

public void setUp() {
    MockitoAnnotations.initMocks(this);
    // ...
}

答案 1 :(得分:-1)

您的userPreference对象为null,但您尝试在其上调用方法。如果您发布所有代码,将会更容易。

Mock对象的想法是正确的 - 但你没有使用Mock对象,你在真实对象上调用when(),但尚未创建,因此是NPE。