As we mentioned before, if tested object interacts with the Android framework, this test is an Instrumented test which means needs to be run on real devices or simulate. These kinds of tests will take the most time. This article, we'll introduce how to run tests as local tests by mocking the android framework.
From the previous registration sample, we want to save loginId after sign up success. SharedPreference is a good way to save data.
We already know it’s hard to test writing non UI logic in Activity. So, let's create a Repository to save data by using SharedPreference.
class Repository(val context: Context) {
// save UserId to SharePreference
fun saveUserId(id: String) {
val sharedPreference =
context.getSharedPreferences(
"USER_DATA", Context.MODE_PRIVATE)
sharedPreference.edit().putString("USER_ID", id).commit()
}
}
Call Repository(this).saveUserId(loginId)
when sign up success in Activity.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
send.setOnClickListener {
...
// sign up success, saveUserId
Repository(this).saveUserId(loginId)
}
}
Start testing
Add a dependency to MockK library.
dependencies {
testImplementation 'io.mockk:mockk:1.9.3'
}
Step:
- Mock Context and SharePreference.
- Use
every returns
to return mocking sharedPreference. - Call tested object
repository.saveUserId(userId).
- Use
verify
to checksharedPrefesEditor.putString()
is pass right parameter. - Use
verify
to checksharedPrefsEditor.commit()
is called.
@Test
fun saveUserId() {
// 1. Mock Context and SharePreference
val sharedPrefs = mockk<SharedPreferences>(relaxed = true)
val sharedPrefsEditor =
mockk<SharedPreferences.Editor>(relaxed = true)
val context = mockk<Context>(relaxed = true)
// 2. Use every returns to return mocking sharedPreference.
every{context.getSharedPreferences(any(),any())}
.returns(sharedPrefs)
every{sharedPrefs.edit()}
.returns(sharedPrefsEditor)
every{sharedPrefsEditor.putString(any(), any())}
.returns(sharedPrefsEditor)
val userId = "A1234567"
val preKey = "USER_ID"
// 3. Call tested object repository.saveUserId(userId)
val repository = Repository(context)
repository.saveUserId(userId)
// 4. Use verify to check sharedPrefesEditor.putString() is pass right parameter. verify{sharedPrefsEditor.putString(eq(preKey), eq(userId)) }
// 5. Use verify to check sharedPrefsEditor.commit() is called.
verify{sharedPrefsEditor.commit()}
}
Click the green triangle to run the test. You'll see the testing duration is 20ms. Running a local test takes less time than the Instrument test.
Github:
https://github.com/evanchen76/AndroidTDD_MockSharedPreference
Next:
Android TDD Part 8 — Instrumented Tests