Reputation: 1
Below is a function in our Android application designed to update the app with a new installation of its current version. However, each approach I've attempted has encountered significant obstacles, such as final classes preventing sections from being mocked, HttpsURLConnection necessitating mocking, Robolectric refusing to run tests without directly reporting the issue, instrumented tests' inability to mock values, and using interfaces to provide mock values but introducing so much mocked functionality that the test no longer verifies the original functionality.
I'm not completely new to android development as a whole, but haven't had much experience with its testing. It'd really help if someone could tell me what approach I should be taking for the below function. But if there is a method for identifying the best approach for any given code, I feel that would be greatly significant in helping me improve.
I understand that this question may be a clone but I believe I currently lack the knowhow to track down this answer myself because I already wasted half a day doing so. The task has been shelved for now but ideally id like to actually implement some form automated tests.
private fun doUpdate() {
if (!portal.updateIsAvailable()) {
updateStatus(getString(R.string.already_running_the_latest_version_press_play_to_start))
startBackgroundTasks()
return
}
updateStatus(getString(R.string.downloading_new_version))
val connection =
URL(portal.latestVersionDownloadUrl()).openConnection() as HttpsURLConnection
connection.sslSocketFactory = sslContext.socketFactory
connection.instanceFollowRedirects = true
connection.requestMethod = "GET"
try {
if (connection.responseCode != 200) {
updateStatus(getString(R.string.version_download_error, connection.responseMessage))
return
}
val installer = packageManager.packageInstaller
val params =
PackageInstaller.SessionParams(PackageInstaller.SessionParams.MODE_FULL_INSTALL)
params.setAppPackageName(packageName)
val sessionId = installer.createSession(params)
val session = installer.openSession(sessionId)
val outputStream = session.openWrite("app_data", 0, connection.contentLength.toLong())
outputStream.use { connection.inputStream.copyTo(it) }
val intentFlags =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) PendingIntent.FLAG_MUTABLE else 0
val intent = PendingIntent.getBroadcast(
this,
sessionId,
Intent(INTENT_PACKAGE_INSTALLER_STATUS),
intentFlags
)
session.commit(intent.intentSender)
} catch (e: Exception) {
updateStatus(getString(R.string.update_error) + e.message)
Log.e("update", "update failed", e)
}
}
(for context portal is referring to a final kotlin class containing code to interact with an API and I need to ensure the project remains mostly in kotlin + compatible with android 5.1 - 11)
As previously stated I've attempted constructing both unit and instrumented tests, but the functions test(s) have run into many issues in both scenarios due to their heavy reliance on external code. Additionally, adjusting the original code and abstracting calls with an interface to mock values results in mocking so much that the real functionality would never be tested.
I really just need to know the correct approach to take, or whether trial and error is the only way.
Thank you for your time.
Upvotes: 0
Views: 39