Skip to content

Instantly share code, notes, and snippets.

@sheerazam
Last active March 25, 2021 16:03
Show Gist options
  • Save sheerazam/cdaa24e13cf834499686ff5207b0da3c to your computer and use it in GitHub Desktop.
Save sheerazam/cdaa24e13cf834499686ff5207b0da3c to your computer and use it in GitHub Desktop.
End to End Test using MockWebserver
import androidx.test.platform.app.InstrumentationRegistry
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Before
import org.koin.core.context.stopKoin
import org.koin.test.KoinTest
import java.io.BufferedReader
import java.io.Reader
abstract class BaseUITest : KoinTest {
/**
* For MockWebServer instance
*/
lateinit var mockServer: MockWebServer
/**
* Default, let server be shut down
*/
private var mShouldStart = false
@Before
open fun setUp() {
startMockServer(true)
}
/**
* Reads input file and converts to json
*/
fun getJson(path: String): String {
var content: String = ""
val testContext = InstrumentationRegistry.getInstrumentation().context
val inputStream = testContext.assets.open(path)
val reader = BufferedReader(inputStream.reader() as Reader?)
reader.use { reader ->
content = reader.readText()
}
return content
}
/**
* Start Mockwebserver
*/
private fun startMockServer(shouldStart: Boolean) {
if (shouldStart) {
mShouldStart = shouldStart
mockServer = MockWebServer()
mockServer.start(8080)
}
}
/**
* Stop Mockwebserver
*/
private fun stopMockServer() {
if (mShouldStart) {
mockServer.shutdown()
}
}
fun <T> getValueFromResultModel(resultUIModel: ApiResultUIModel<T>?): T? {
return when (val result = resultUIModel?.showSuccess?.peek()) {
is Result.Success -> {
result.data
}
is Result.Error -> {
null
}
else -> null
}
}
@After
open fun tearDown() {
//Stop Mock server
stopMockServer()
//Stop Koin as well
stopKoin()
}
}
def mockwebserver_version = '4.1.0'
def coroutines_version = "1.3.7"
////////// -------- Testing --------- ////////////
implementation 'androidx.test.espresso:espresso-idling-resource:3.3.0'
androidTestImplementation('com.schibsted.spain:barista:3.9.0') {
exclude group: 'org.jetbrains.kotlin' // Only if you already use Kotlin in your project
}
androidTestImplementation "org.koin:koin-test:$koin_version"
androidTestImplementation "androidx.arch.core:core-testing:2.1.0"
androidTestImplementation "com.squareup.okhttp3:mockwebserver:$mockwebserver_version"
androidTestImplementation "androidx.fragment:fragment-testing:1.3.1"
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'com.jakewharton.espresso:okhttp3-idling-resource:1.0.0'
androidTestImplementation "io.mockk:mockk-android:1.10.6"
androidTestImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines_version"
fun clickOnChildViewWithId(id: Int): ViewAction {
return object : ViewAction {
override fun getConstraints(): Matcher<View>? {
return null
}
override fun getDescription(): String {
return "Click on a child view with specified id."
}
override fun perform(uiController: UiController, view: View) {
val v = view.findViewById<View>(id) as Button
v.performClick()
}
}
}
object FileReader {
fun readStringFromFile(fileName: String): String {
try {
val inputStream = (InstrumentationRegistry.getInstrumentation().targetContext
.applicationContext).assets.open(fileName)
val builder = StringBuilder()
val reader = InputStreamReader(inputStream, "UTF-8")
reader.readLines().forEach {
builder.append(it)
}
return builder.toString()
} catch (e: IOException) {
throw e
}
}
}
fun typeTextInChildViewWithId(id: Int, textToBeTyped: String): ViewAction {
return object : ViewAction {
override fun getConstraints(): Matcher<View>? {
return null
}
override fun getDescription(): String {
return "Click on a child view with specified id."
}
override fun perform(uiController: UiController, view: View) {
val v = view.findViewById<View>(id) as EditText
v.setText(textToBeTyped)
}
}
}
import android.os.SystemClock
import android.util.Log
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import androidx.fragment.app.testing.launchFragmentInContainer
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.IdlingRegistry
import androidx.test.espresso.contrib.RecyclerViewActions
import androidx.test.espresso.matcher.ViewMatchers.withContentDescription
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import com.jakewharton.espresso.OkHttp3IdlingResource
import com.xwray.groupie.GroupieViewHolder
import com.xwray.groupie.Item
import io.mockk.MockKAnnotations
import junit.framework.Assert.assertTrue
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runBlockingTest
import okhttp3.mockwebserver.Dispatcher
import okhttp3.mockwebserver.MockResponse
import okhttp3.mockwebserver.RecordedRequest
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.koin.android.ext.koin.androidContext
import org.koin.core.component.inject
import org.koin.core.context.startKoin
import java.net.HttpURLConnection
@RunWith(AndroidJUnit4::class)
class WebLeadTest : BaseUITest() {
val apiFactory: Apifactory by inject()
@get:Rule
var instantExecutorRule = InstantTaskExecutorRule()
@Before
override fun setUp() {
super.setUp()
MockKAnnotations.init(this)
val context = InstrumentationRegistry.getInstrumentation().targetContext
startKoin {
androidContext(context)
modules(generateTestAppComponent())
}
IdlingRegistry.getInstance().register(
OkHttp3IdlingResource.create(
"okhttp",
apiFactory.vpClient
))
}
@OptIn(ExperimentalCoroutinesApi::class)
@Test
fun testWebLeadShouldSendDataCorrectly() = runBlockingTest {
val scenario = launchFragmentInContainer<PropertyDetailsBottomSheetFragment>(themeResId = R.style.AppBaseTheme)
mockServer.dispatcher = object : Dispatcher() {
override fun dispatch(request: RecordedRequest): MockResponse {
return if (request.path?.contains("detailApi") == true) {
MockResponse()
.setResponseCode(HttpURLConnection.HTTP_OK)
.setBody(FileReader.readStringFromFile("firstApiResponse.json"))
} else {
MockResponse()
.setResponseCode(HttpURLConnection.HTTP_OK)
.setBody(FileReader.readStringFromFile("otherApiResponse.json"))
}
}
}
SystemClock.sleep(1000)
var propertyDetailsFragment: PropertyDetailsBottomSheetFragment? = null
scenario.onFragment { fragment ->
propertyDetailsFragment = fragment
fragment.myViewModel1.selectedProperty?.CD_MLS = "1234"
advanceTimeBy(5000)
}
advanceTimeBy(5000)
assertTrue(propertyDetailsFragment != null)
assertTrue(propertyDetailsFragment?.group?.differ?.currentList?.isNotEmpty() == true)
val itemFirstName = propertyDetailsFragment?.group?.differ?.currentList?.first {
it.id.toString() == "cell_id1"
}
assertTrue(itemFirstName != null)
typeTextInRecyclerView(fragment = propertyDetailsFragment!!,
text = "Sheeraz", item = itemFirstName!!, editTextId = R.id.txtText)
val itemLastName = propertyDetailsFragment?.group?.differ?.currentList?.first {
it.id.toString() == "cell_id1"
}
assertTrue(itemLastName != null)
typeTextInRecyclerView(fragment = propertyDetailsFragment!!,
text = "Ahmed", item = itemLastName!!, editTextId = R.id.txtText)
val itemEmail = propertyDetailsFragment?.group?.differ?.currentList?.first {
it.id.toString() == "cell_id2"
}
assertTrue(itemEmail != null)
typeTextInRecyclerView(fragment = propertyDetailsFragment!!,
text = "abc@abc.com", item = itemEmail!!, editTextId = R.id.txtText)
val itemNotes = propertyDetailsFragment?.group?.differ?.currentList?.first {
it.id.toString() == "cell_id3"
}
assertTrue(itemNotes != null)
typeTextInRecyclerView(fragment = propertyDetailsFragment!!,
text = "test notes", item = itemNotes!!, editTextId = R.id.txtText)
val itemSendButton = propertyDetailsFragment?.group?.differ?.currentList?.first {
it.id.toString() == "cell_id4"
}
clickOnSendButton(fragment = propertyDetailsFragment!!, item = itemSendButton!!)
SystemClock.sleep(2000)
val value = propertyDetailsFragment?.myViewModel2?.sendMeInfoState?.getOrAwaitValue()
advanceTimeBy(5000)
assertTrue(getValueFromResultModel(value)?.CELLS?.isNotEmpty() == true)
Log.d("PropertyTest", mockServer.takeRequest().requestLine)
val requestData = mockServer.takeRequest().body.readUtf8Line()!!
Log.d("PropertyTest", requestData)
assertTrue(requestData.contains("CC_FIRSTNAME=Sheeraz"))
assertTrue(requestData.contains("CC_LASTNAME=Ahmed"))
assertTrue(requestData.contains("cd_MLS=1234"))
assertTrue(requestData.contains("CE_EMAIL=abc@abc.com"))
assertTrue(requestData.contains("CI_DS_NOTES=test%20notes"))
assertTrue(requestData.contains("CI_MLS_NUMBER=12345"))
assertTrue(requestData.contains("IS_SHOWING="))
}
fun typeTextInRecyclerView(fragment: PropertyDetailsBottomSheetFragment, text: String, editTextId: Int, item: Item<GroupieViewHolder>) {
val context = InstrumentationRegistry.getInstrumentation().targetContext
onView(withContentDescription(context.resources.getString(R.string.property_details_main_recycler_view)))
.perform(RecyclerViewActions
.actionOnItemAtPosition<GroupieViewHolder>(fragment.group.getPosition(item),
typeTextInChildViewWithId(editTextId, text)))
}
fun clickOnSendButton(fragment: PropertyDetailsBottomSheetFragment, item: Item<GroupieViewHolder>) {
val context = InstrumentationRegistry.getInstrumentation().targetContext
onView(withContentDescription(context.resources.getString(R.string.property_details_main_recycler_view)))
.perform(RecyclerViewActions
.actionOnItemAtPosition<GroupieViewHolder>(fragment.group.getPosition(item),
clickOnChildViewWithId(R.id.button)))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment