Sim*_*mon 5 android unit-testing mockito android-context
我从谷歌的示例中获得了如何SharedPreferences通过创建SharedPreferencesHelper类来测试代码的灵感:
您可以看到该类使用类中硬编码的实际字符串作为键的sharedPreferences- 这是类的提取:
public class SharedPreferencesHelper {
// Keys for saving values in SharedPreferences.
static final String KEY_NAME = "key_name";
static final String KEY_DOB = "key_dob_millis";
static final String KEY_EMAIL = "key_email";
public boolean savePersonalInfo(SharedPreferenceEntry sharedPreferenceEntry){
// Start a SharedPreferences transaction.
SharedPreferences.Editor editor = mSharedPreferences.edit();
editor.putString(KEY_NAME, sharedPreferenceEntry.getName());
editor.putLong(KEY_DOB, sharedPreferenceEntry.getDateOfBirth().getTimeInMillis());
editor.putString(KEY_EMAIL, sharedPreferenceEntry.getEmail());
// Commit changes to SharedPreferences.
return editor.commit();
}
Run Code Online (Sandbox Code Playgroud)
在SharedPreferencesHelperTest这里使用他们的类测试时,他们sharedPreferences使用上面类中定义的相同变量访问模拟:
该类的摘录显示如下:
when(mMockSharedPreferences.getString(eq(SharedPreferencesHelper.KEY_NAME), anyString()))
.thenReturn(mSharedPreferenceEntry.getName());
when(mMockSharedPreferences.getString(eq(SharedPreferencesHelper.KEY_EMAIL), anyString()))
.thenReturn(mSharedPreferenceEntry.getEmail());
when(mMockSharedPreferences.getLong(eq(SharedPreferencesHelper.KEY_DOB), anyLong()))
.thenReturn(mSharedPreferenceEntry.getDateOfBirth().getTimeInMillis());
Run Code Online (Sandbox Code Playgroud)
谷歌这样做的方式允许他们绕过使用a context从string.xml资源文件中拉出一个字符串并在内部查询它的问题,sharedPreferences就像通常假设通过使用它发生一样getString(),即:
mSharedPreferences.getString(context.getString(R.string.name),"");
Run Code Online (Sandbox Code Playgroud)
但是,我已经读过它是不可能使用的,context.getString因为它是最终方法而且mockito不能模拟最终方法:
然后,我如何使用mockito对任何方法进行单元测试getString?任何方法getString都不起作用,我的单元测试将失败.
这是我写的课程,我SharedPreferences想用以下代码sharedPreferences编写的密钥进行测试getStrings:
public class SharedPreferencesHelper {
// The injected SharedPreferences implementation to use for persistence.
private final SharedPreferences mSharedPreferences;
private Context context;
public SharedPreferencesHelper(SharedPreferences sharedPreferences, Context context) {
mSharedPreferences = sharedPreferences;
this.context = context;
}
public boolean saveName(String name) {
// Start a SharedPreferences transaction.
SharedPreferences.Editor editor = mSharedPreferences.edit();
editor.putString(context.getString(R.string.name), name);
return editor.commit();
}
public String fetchName() {
// Start a SharedPreferences transaction.
return mSharedPreferences.getString(context.getString(R.string.name),"");
}
public boolean saveGender(String gender) {
SharedPreferences.Editor editor = mSharedPreferences.edit();
editor.putString(context.getString(R.string.gender), gender);
return editor.commit();
}
}
Run Code Online (Sandbox Code Playgroud)
这是我为上述类编写的测试 - 它与google的SharedPreferencesHelperTest非常相似:
@RunWith(MockitoJUnitRunner.class)
public class SharedPreferencesHelperTest {
private static final String TEST_NAME = "Test name";
private SharedPreferencesHelper mMockSharedPreferencesHelper;
@Mock
SharedPreferences mMockSharedPreferences;
@Mock
SharedPreferences.Editor mMockEditor;
@Mock
MockContext context;
@Before
public void setUp() throws Exception {
// Create a mocked SharedPreferences.
mMockSharedPreferencesHelper = createMockSharedPreference();
}
@Test
public void testSaveName() throws Exception {
boolean success = mMockSharedPreferencesHelper.saveName(TEST_NAME);
Timber.e("success " + success);
assertThat("Checking that name was saved... returns true = " + success,
success, is(true));
String name = mMockSharedPreferencesHelper.fetchName();
Timber.e("name " + name);
assertThat("Checking that name has been persisted and read correctly " + name,
TEST_NAME,
is(name));
}
/**
* Creates a mocked SharedPreferences.
*/
private SharedPreferencesHelper createMockSharedPreference() {
// Mocking reading the SharedPreferences as if mMockSharedPreferences was previously written
// correctly.
when(mMockSharedPreferences.getString(Matchers.eq("name"), anyString()))
.thenReturn(TEST_NAME);
when(mMockSharedPreferences.getString(Matchers.eq("gender"), anyString()))
.thenReturn("M");
// Mocking a successful commit.
when(mMockEditor.commit()).thenReturn(true);
// Return the MockEditor when requesting it.
when(mMockSharedPreferences.edit()).thenReturn(mMockEditor);
return new SharedPreferencesHelper(mMockSharedPreferences, context);
}
}
Run Code Online (Sandbox Code Playgroud)
运行测试失败,因为我getString在SharedPreferencesHelper课堂上使用过.如果我对密钥进行硬编码,我将不会收到错误,即:
public String fetchName() {
// Start a SharedPreferences transaction.
return mSharedPreferences.getString("name","");
}
Run Code Online (Sandbox Code Playgroud)
不应该在代码中对字符串进行硬编码,那么如何解决这个难题呢?
小智 5
您可以通过不使用Context获取字符串资源来解决此问题,而是使用Resources类.Resources有相同的getString方法,但它不是最终的.
https://developer.android.com/reference/android/content/res/Resources.html#getString(int)
或者你可以尝试Robolectric,它可以解决这个问题,因为它们实现了上下文.
| 归档时间: |
|
| 查看次数: |
3359 次 |
| 最近记录: |