我做了一个简单的检测测试,以验证从SharedPreferences读取的数据是否在UI上正确显示。在Activity的onResume()方法中执行数据检索和显示操作。
但问题是,即使我嘲笑了偏好对象并定义了假的返回值,活动仍然从真实偏好中读取数据,忽略when(...).thenReturn(...)
声明。任何人都可以有什么想法吗?
@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
MockitoAnnotations.initMocks(this);
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");
}
public void saveName(String name){
prefEditor.putString(context.getString(R.string.pref_name), name);
prefEditor.apply();
}
[编辑]
我原始活动的简化版本:
public class EditProfileActivity extends AppCompatActivity{
//...
private UserPreference userPreference;
//...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
userPreference = new UserPreference(this);
setContentView(R.layout.activity_edit_profile);
//...
}
@Override
protected void onResume() {
super.onResume();
//...
String name = userPreference.getName();
nameEdt.setText(name); //Display the name on an EditText
//...
}
}
答案 0 :(得分:0)
创建了onCreate
模拟,但活动仍然使用在其userPreference
方法中创建的模拟。您需要将该活动的userPreference
字段设置为模拟。
有几种方法可以做到:
为@Before
字段添加setter方法,并使用@Before
public void setUp(){
...
EditProfileActivity activity = activityTestRule.launchActivity(intent);
activity.setUserPreference(mockedUserPreference);
}
方法调用它:
userPreference
这很简单但很难看:你改变活动只是为了适应测试。
通过反射设置@Before
public void setUp(){
...
EditProfileActivity activity = activityTestRule.launchActivity(intent);
Field userPreferenceField = activity.getClass().getDeclaredField("userPreference");
field.setAccessible(true);
userPreferenceField.set(activity, mockedUserPreference);
}
字段:
UserPreference
这是一个脆弱的测试:更改字段名称会破坏它而不会出现编译错误。但是,活动不必改变,所以当你无法改变它时它很有用。
不要在onCreate
方法中实例化fiddler auto responder rule editor
。在普通的Java中,我将它添加为构造函数参数,但我不知道这是否适用于Android。也许使用依赖注入框架,它们非常适合用于模拟:Android and Dependency Injection