Issue#30 Add additional Test for missing field and exact copy of how the CodeKataSessionExpirationTest should look

This commit is contained in:
Gergely Hegedus 2022-01-24 20:44:55 +02:00
parent 7544c6b784
commit 7739b10101
2 changed files with 116 additions and 3 deletions

View file

@ -0,0 +1,111 @@
package org.fnives.test.showcase.network.content
import kotlinx.coroutines.runBlocking
import okhttp3.mockwebserver.MockResponse
import okhttp3.mockwebserver.MockWebServer
import org.fnives.test.showcase.model.network.BaseUrl
import org.fnives.test.showcase.model.session.Session
import org.fnives.test.showcase.network.auth.CodeKataLoginRemoteSourceTest.Companion.readResourceFile
import org.fnives.test.showcase.network.di.createNetworkModules
import org.fnives.test.showcase.network.session.NetworkSessionExpirationListener
import org.fnives.test.showcase.network.session.NetworkSessionLocalStorage
import org.fnives.test.showcase.network.shared.exceptions.NetworkException
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.Assertions
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import org.koin.core.context.startKoin
import org.koin.core.context.stopKoin
import org.koin.test.KoinTest
import org.koin.test.inject
import org.mockito.kotlin.anyOrNull
import org.mockito.kotlin.doAnswer
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.mockito.kotlin.times
import org.mockito.kotlin.verify
import org.mockito.kotlin.verifyNoMoreInteractions
import org.mockito.kotlin.verifyZeroInteractions
import org.mockito.kotlin.whenever
import retrofit2.HttpException
class PlainSessionExpirationTest : KoinTest {
private val sut by inject<ContentRemoteSource>()
private lateinit var mockWebServer: MockWebServer
private lateinit var mockNetworkSessionLocalStorage: NetworkSessionLocalStorage
private lateinit var mockNetworkSessionExpirationListener: NetworkSessionExpirationListener
@BeforeEach
fun setUp() {
mockWebServer = MockWebServer()
mockWebServer.start()
mockNetworkSessionLocalStorage = mock()
mockNetworkSessionExpirationListener = mock()
startKoin {
modules(
createNetworkModules(
baseUrl = BaseUrl(mockWebServer.url("mockserver/").toString()),
enableLogging = true,
networkSessionExpirationListenerProvider = { mockNetworkSessionExpirationListener },
networkSessionLocalStorageProvider = { mockNetworkSessionLocalStorage }
).toList()
)
}
}
@AfterEach
fun tearDown() {
stopKoin()
mockWebServer.shutdown()
}
@DisplayName("GIVEN 401 THEN refresh token ok response WHEN content requested THE tokens are refreshed and request retried with new tokens")
@Test
fun successRefreshResultsInRequestRetry() = runBlocking {
mockWebServer.enqueue(MockResponse().setResponseCode(401))
mockWebServer.enqueue(MockResponse().setResponseCode(200).setBody(readResourceFile("success_response_login.json")))
mockWebServer.enqueue(MockResponse().setResponseCode(200).setBody("[]"))
var sessionToReturnByMock: Session? = Session(accessToken = "expired-access", refreshToken = "expired-refresh")
whenever(mockNetworkSessionLocalStorage.session).doAnswer { sessionToReturnByMock }
doAnswer { sessionToReturnByMock = it.arguments[0] as Session? }
.whenever(mockNetworkSessionLocalStorage).session = anyOrNull()
sut.get()
mockWebServer.takeRequest()
val refreshRequest = mockWebServer.takeRequest()
val contentRequestAfterRefreshed = mockWebServer.takeRequest()
Assertions.assertEquals("PUT", refreshRequest.method)
Assertions.assertEquals("/mockserver/login/expired-refresh", refreshRequest.path)
Assertions.assertEquals(null, refreshRequest.getHeader("Authorization"))
Assertions.assertEquals("Android", refreshRequest.getHeader("Platform"))
Assertions.assertEquals("", refreshRequest.body.readUtf8())
Assertions.assertEquals("login-access", contentRequestAfterRefreshed.getHeader("Authorization"))
verifyZeroInteractions(mockNetworkSessionExpirationListener)
}
@DisplayName("GIVEN 401 THEN failing refresh WHEN content requested THE error is returned and callback is Called")
@Test
fun failingRefreshResultsInSessionExpiration() = runBlocking {
val currentSession = Session(accessToken = "expired-access", refreshToken = "expired-refresh")
whenever(mockNetworkSessionLocalStorage.session).doReturn(currentSession)
mockWebServer.enqueue(MockResponse().setResponseCode(401))
mockWebServer.enqueue(MockResponse().setResponseCode(400))
val actual = Assertions.assertThrows(NetworkException::class.java) {
runBlocking { sut.get() }
}
Assertions.assertEquals("HTTP 401 Client Error", actual.message)
Assertions.assertTrue(actual.cause is HttpException)
verify(mockNetworkSessionLocalStorage, times(3)).session
verify(mockNetworkSessionLocalStorage, times(1)).session = null
verifyNoMoreInteractions(mockNetworkSessionLocalStorage)
verify(mockNetworkSessionExpirationListener, times(1)).onSessionExpired()
}
}

View file

@ -30,6 +30,7 @@ import org.mockito.kotlin.verify
import org.mockito.kotlin.verifyNoMoreInteractions import org.mockito.kotlin.verifyNoMoreInteractions
import org.mockito.kotlin.verifyZeroInteractions import org.mockito.kotlin.verifyZeroInteractions
import org.mockito.kotlin.whenever import org.mockito.kotlin.whenever
import retrofit2.HttpException
@Suppress("TestFunctionName") @Suppress("TestFunctionName")
class SessionExpirationTest : KoinTest { class SessionExpirationTest : KoinTest {
@ -96,8 +97,6 @@ class SessionExpirationTest : KoinTest {
ContentData.refreshSuccessResponse.accessToken, ContentData.refreshSuccessResponse.accessToken,
retryAfterTokenRefreshRequest.getHeader("Authorization") retryAfterTokenRefreshRequest.getHeader("Authorization")
) )
verify(mockNetworkSessionLocalStorage, times(1)).session =
ContentData.refreshSuccessResponse
verifyZeroInteractions(mockNetworkSessionExpirationListener) verifyZeroInteractions(mockNetworkSessionExpirationListener)
} }
@ -108,9 +107,12 @@ class SessionExpirationTest : KoinTest {
mockServerScenarioSetup.setScenario(ContentScenario.Unauthorized(usingRefreshedToken = false), validateArguments = false) mockServerScenarioSetup.setScenario(ContentScenario.Unauthorized(usingRefreshedToken = false), validateArguments = false)
mockServerScenarioSetup.setScenario(RefreshTokenScenario.Error, validateArguments = false) mockServerScenarioSetup.setScenario(RefreshTokenScenario.Error, validateArguments = false)
Assertions.assertThrows(NetworkException::class.java) { val actual = Assertions.assertThrows(NetworkException::class.java) {
runBlocking { sut.get() } runBlocking { sut.get() }
} }
Assertions.assertEquals("HTTP 401 Client Error", actual.message)
Assertions.assertTrue(actual.cause is HttpException)
verify(mockNetworkSessionLocalStorage, times(3)).session verify(mockNetworkSessionLocalStorage, times(3)).session
verify(mockNetworkSessionLocalStorage, times(1)).session = null verify(mockNetworkSessionLocalStorage, times(1)).session = null
verifyNoMoreInteractions(mockNetworkSessionLocalStorage) verifyNoMoreInteractions(mockNetworkSessionLocalStorage)