Issue#11 Create Turbine variant of Flow Tests
This commit is contained in:
parent
b52652ed67
commit
a71fa67de2
4 changed files with 428 additions and 50 deletions
|
|
@ -1,6 +1,5 @@
|
|||
package org.fnives.test.showcase.core.content
|
||||
|
||||
import app.cash.turbine.test
|
||||
import kotlinx.coroutines.CompletableDeferred
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.flow.take
|
||||
|
|
@ -147,28 +146,4 @@ internal class ContentRepositoryTest {
|
|||
Assertions.assertFalse(actual.isCompleted)
|
||||
actual.cancel()
|
||||
}
|
||||
|
||||
@DisplayName("GIVEN content response THEN error WHEN fetched THEN only 4 items are emitted")
|
||||
@Test
|
||||
fun noAdditionalItemsEmittedWithTurbine() = runTest {
|
||||
val exception = RuntimeException()
|
||||
val expected = listOf(
|
||||
Resource.Loading(),
|
||||
Resource.Success(emptyList()),
|
||||
Resource.Loading(),
|
||||
Resource.Error<List<Content>>(UnexpectedException(exception))
|
||||
)
|
||||
var first = true
|
||||
whenever(mockContentRemoteSource.get()).doAnswer {
|
||||
if (first) emptyList<Content>().also { first = false } else throw exception
|
||||
}
|
||||
|
||||
sut.contents.test {
|
||||
sut.fetch()
|
||||
expected.forEach { expectedItem ->
|
||||
Assertions.assertEquals(expectedItem, awaitItem())
|
||||
}
|
||||
Assertions.assertTrue(cancelAndConsumeRemainingEvents().isEmpty())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
package org.fnives.test.showcase.core.content
|
||||
|
||||
import app.cash.turbine.test
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.take
|
||||
import kotlinx.coroutines.flow.toList
|
||||
import kotlinx.coroutines.test.advanceUntilIdle
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.fnives.test.showcase.core.storage.content.FavouriteContentLocalStorage
|
||||
import org.fnives.test.showcase.model.content.Content
|
||||
|
|
@ -151,15 +152,18 @@ internal class GetAllContentUseCaseTest {
|
|||
Resource.Success(listOf(FavouriteContent(content, true)))
|
||||
)
|
||||
|
||||
sut.get().test {
|
||||
contentFlow.value = Resource.Success(listOf(content))
|
||||
favouriteContentIdFlow.value = listOf(ContentId("a"))
|
||||
|
||||
expected.forEach { expectedItem ->
|
||||
Assertions.assertEquals(expectedItem, awaitItem())
|
||||
}
|
||||
Assertions.assertTrue(cancelAndConsumeRemainingEvents().isEmpty())
|
||||
val actual = async(coroutineContext) {
|
||||
sut.get().take(3).toList()
|
||||
}
|
||||
advanceUntilIdle()
|
||||
|
||||
contentFlow.value = Resource.Success(listOf(content))
|
||||
advanceUntilIdle()
|
||||
|
||||
favouriteContentIdFlow.value = listOf(ContentId("a"))
|
||||
advanceUntilIdle()
|
||||
|
||||
Assertions.assertEquals(expected, actual.getCompleted())
|
||||
}
|
||||
|
||||
@DisplayName("GIVEN loading then data then removed favourite WHEN observed THEN loading then correct favourites are returned")
|
||||
|
|
@ -174,15 +178,18 @@ internal class GetAllContentUseCaseTest {
|
|||
Resource.Success(listOf(FavouriteContent(content, false)))
|
||||
)
|
||||
|
||||
sut.get().test {
|
||||
contentFlow.value = Resource.Success(listOf(content))
|
||||
favouriteContentIdFlow.value = emptyList()
|
||||
|
||||
expected.forEach { expectedItem ->
|
||||
Assertions.assertEquals(expectedItem, awaitItem())
|
||||
}
|
||||
Assertions.assertTrue(cancelAndConsumeRemainingEvents().isEmpty())
|
||||
val actual = async(coroutineContext) {
|
||||
sut.get().take(3).toList()
|
||||
}
|
||||
advanceUntilIdle()
|
||||
|
||||
contentFlow.value = Resource.Success(listOf(content))
|
||||
advanceUntilIdle()
|
||||
|
||||
favouriteContentIdFlow.value = emptyList()
|
||||
advanceUntilIdle()
|
||||
|
||||
Assertions.assertEquals(expected, actual.getCompleted())
|
||||
}
|
||||
|
||||
@DisplayName("GIVEN loading then data then loading WHEN observed THEN loading then correct favourites then loading are returned")
|
||||
|
|
@ -197,14 +204,17 @@ internal class GetAllContentUseCaseTest {
|
|||
Resource.Loading()
|
||||
)
|
||||
|
||||
sut.get().test {
|
||||
contentFlow.value = Resource.Success(listOf(content))
|
||||
contentFlow.value = Resource.Loading()
|
||||
|
||||
expected.forEach { expectedItem ->
|
||||
Assertions.assertEquals(expectedItem, awaitItem())
|
||||
}
|
||||
Assertions.assertTrue(cancelAndConsumeRemainingEvents().isEmpty())
|
||||
val actual = async(coroutineContext) {
|
||||
sut.get().take(3).toList()
|
||||
}
|
||||
advanceUntilIdle()
|
||||
|
||||
contentFlow.value = Resource.Success(listOf(content))
|
||||
advanceUntilIdle()
|
||||
|
||||
contentFlow.value = Resource.Loading()
|
||||
advanceUntilIdle()
|
||||
|
||||
Assertions.assertEquals(expected, actual.getCompleted())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,165 @@
|
|||
package org.fnives.test.showcase.core.content
|
||||
|
||||
import app.cash.turbine.test
|
||||
import kotlinx.coroutines.CompletableDeferred
|
||||
import kotlinx.coroutines.flow.take
|
||||
import kotlinx.coroutines.flow.toList
|
||||
import kotlinx.coroutines.test.UnconfinedTestDispatcher
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.fnives.test.showcase.core.shared.UnexpectedException
|
||||
import org.fnives.test.showcase.model.content.Content
|
||||
import org.fnives.test.showcase.model.content.ContentId
|
||||
import org.fnives.test.showcase.model.content.ImageUrl
|
||||
import org.fnives.test.showcase.model.shared.Resource
|
||||
import org.fnives.test.showcase.network.content.ContentRemoteSource
|
||||
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.mockito.kotlin.doAnswer
|
||||
import org.mockito.kotlin.doReturn
|
||||
import org.mockito.kotlin.doSuspendableAnswer
|
||||
import org.mockito.kotlin.doThrow
|
||||
import org.mockito.kotlin.mock
|
||||
import org.mockito.kotlin.times
|
||||
import org.mockito.kotlin.verify
|
||||
import org.mockito.kotlin.verifyNoMoreInteractions
|
||||
import org.mockito.kotlin.whenever
|
||||
|
||||
class TurbineContentRepositoryTest {
|
||||
|
||||
private lateinit var sut: ContentRepository
|
||||
private lateinit var mockContentRemoteSource: ContentRemoteSource
|
||||
|
||||
@BeforeEach
|
||||
fun setUp() {
|
||||
mockContentRemoteSource = mock()
|
||||
sut = ContentRepository(mockContentRemoteSource)
|
||||
}
|
||||
|
||||
@DisplayName("GIVEN no interaction THEN remote source is not called")
|
||||
@Test
|
||||
fun fetchingIsLazy() {
|
||||
verifyNoMoreInteractions(mockContentRemoteSource)
|
||||
}
|
||||
|
||||
@DisplayName("GIVEN content response WHEN content observed THEN loading AND data is returned")
|
||||
@Test
|
||||
fun happyFlow() = runTest {
|
||||
val expected = listOf(
|
||||
Resource.Loading(),
|
||||
Resource.Success(listOf(Content(ContentId("a"), "", "", ImageUrl(""))))
|
||||
)
|
||||
whenever(mockContentRemoteSource.get()).doReturn(
|
||||
listOf(Content(ContentId("a"), "", "", ImageUrl("")))
|
||||
)
|
||||
|
||||
sut.contents.test {
|
||||
expected.forEach { expectedItem ->
|
||||
Assertions.assertEquals(expectedItem, awaitItem())
|
||||
}
|
||||
Assertions.assertTrue(cancelAndConsumeRemainingEvents().isEmpty())
|
||||
}
|
||||
}
|
||||
|
||||
@DisplayName("GIVEN content error WHEN content observed THEN loading AND data is returned")
|
||||
@Test
|
||||
fun errorFlow() = runTest {
|
||||
val exception = RuntimeException()
|
||||
val expected = listOf(
|
||||
Resource.Loading(),
|
||||
Resource.Error<List<Content>>(UnexpectedException(exception))
|
||||
)
|
||||
whenever(mockContentRemoteSource.get()).doThrow(exception)
|
||||
|
||||
sut.contents.test {
|
||||
expected.forEach { expectedItem ->
|
||||
Assertions.assertEquals(expectedItem, awaitItem())
|
||||
}
|
||||
Assertions.assertTrue(cancelAndConsumeRemainingEvents().isEmpty())
|
||||
}
|
||||
}
|
||||
|
||||
@DisplayName("GIVEN saved cache WHEN collected THEN cache is returned")
|
||||
@Test
|
||||
fun verifyCaching() = runTest {
|
||||
val content = Content(ContentId("1"), "", "", ImageUrl(""))
|
||||
val expected = listOf(Resource.Success(listOf(content)))
|
||||
whenever(mockContentRemoteSource.get()).doReturn(listOf(content))
|
||||
sut.contents.take(2).toList()
|
||||
|
||||
sut.contents.test {
|
||||
expected.forEach { expectedItem ->
|
||||
Assertions.assertEquals(expectedItem, awaitItem())
|
||||
}
|
||||
Assertions.assertTrue(cancelAndConsumeRemainingEvents().isEmpty())
|
||||
}
|
||||
verify(mockContentRemoteSource, times(1)).get()
|
||||
}
|
||||
|
||||
@DisplayName("GIVEN no response from remote source WHEN content observed THEN loading is returned")
|
||||
@Test
|
||||
fun loadingIsShownBeforeTheRequestIsReturned() = runTest {
|
||||
val expected = listOf(Resource.Loading<List<Content>>())
|
||||
val suspendedRequest = CompletableDeferred<Unit>()
|
||||
whenever(mockContentRemoteSource.get()).doSuspendableAnswer {
|
||||
suspendedRequest.await()
|
||||
emptyList()
|
||||
}
|
||||
|
||||
sut.contents.test {
|
||||
expected.forEach { expectedItem ->
|
||||
Assertions.assertEquals(expectedItem, awaitItem())
|
||||
}
|
||||
Assertions.assertTrue(cancelAndConsumeRemainingEvents().isEmpty())
|
||||
}
|
||||
suspendedRequest.complete(Unit)
|
||||
}
|
||||
|
||||
@DisplayName("GIVEN content response THEN error WHEN fetched THEN returned states are loading data loading error")
|
||||
@Test
|
||||
fun whenFetchingRequestIsCalledAgain() = runTest(UnconfinedTestDispatcher()) {
|
||||
val exception = RuntimeException()
|
||||
val expected = listOf(
|
||||
Resource.Loading(),
|
||||
Resource.Success(emptyList()),
|
||||
Resource.Loading(),
|
||||
Resource.Error<List<Content>>(UnexpectedException(exception))
|
||||
)
|
||||
var first = true
|
||||
whenever(mockContentRemoteSource.get()).doAnswer {
|
||||
if (first) emptyList<Content>().also { first = false } else throw exception
|
||||
}
|
||||
|
||||
sut.contents.test {
|
||||
sut.fetch()
|
||||
expected.forEach { expectedItem ->
|
||||
Assertions.assertEquals(expectedItem, awaitItem())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@DisplayName("GIVEN content response THEN error WHEN fetched THEN only 4 items are emitted")
|
||||
@Test
|
||||
fun noAdditionalItemsEmitted() = runTest {
|
||||
val exception = RuntimeException()
|
||||
val expected = listOf(
|
||||
Resource.Loading(),
|
||||
Resource.Success(emptyList()),
|
||||
Resource.Loading(),
|
||||
Resource.Error<List<Content>>(UnexpectedException(exception))
|
||||
)
|
||||
var first = true
|
||||
whenever(mockContentRemoteSource.get()).doAnswer {
|
||||
if (first) emptyList<Content>().also { first = false } else throw exception
|
||||
}
|
||||
|
||||
sut.contents.test {
|
||||
sut.fetch()
|
||||
expected.forEach { expectedItem ->
|
||||
Assertions.assertEquals(expectedItem, awaitItem())
|
||||
}
|
||||
Assertions.assertTrue(cancelAndConsumeRemainingEvents().isEmpty())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,228 @@
|
|||
package org.fnives.test.showcase.core.content
|
||||
|
||||
import app.cash.turbine.test
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.fnives.test.showcase.core.storage.content.FavouriteContentLocalStorage
|
||||
import org.fnives.test.showcase.model.content.Content
|
||||
import org.fnives.test.showcase.model.content.ContentId
|
||||
import org.fnives.test.showcase.model.content.FavouriteContent
|
||||
import org.fnives.test.showcase.model.content.ImageUrl
|
||||
import org.fnives.test.showcase.model.shared.Resource
|
||||
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.mockito.kotlin.doReturn
|
||||
import org.mockito.kotlin.mock
|
||||
import org.mockito.kotlin.whenever
|
||||
|
||||
class TurbineGetAllContentUseCaseTest {
|
||||
|
||||
private lateinit var sut: GetAllContentUseCase
|
||||
private lateinit var mockContentRepository: ContentRepository
|
||||
private lateinit var mockFavouriteContentLocalStorage: FavouriteContentLocalStorage
|
||||
private lateinit var contentFlow: MutableStateFlow<Resource<List<Content>>>
|
||||
private lateinit var favouriteContentIdFlow: MutableStateFlow<List<ContentId>>
|
||||
|
||||
@BeforeEach
|
||||
fun setUp() {
|
||||
mockFavouriteContentLocalStorage = mock()
|
||||
mockContentRepository = mock()
|
||||
favouriteContentIdFlow = MutableStateFlow(emptyList())
|
||||
contentFlow = MutableStateFlow(Resource.Loading())
|
||||
whenever(mockFavouriteContentLocalStorage.observeFavourites()).doReturn(
|
||||
favouriteContentIdFlow
|
||||
)
|
||||
whenever(mockContentRepository.contents).doReturn(contentFlow)
|
||||
sut = GetAllContentUseCase(mockContentRepository, mockFavouriteContentLocalStorage)
|
||||
}
|
||||
|
||||
@DisplayName("GIVEN loading AND empty favourite WHEN observed THEN loading is shown")
|
||||
@Test
|
||||
fun loadingResourceWithNoFavouritesResultsInLoadingResource() = runTest {
|
||||
favouriteContentIdFlow.value = emptyList()
|
||||
contentFlow.value = Resource.Loading()
|
||||
val expected = listOf(Resource.Loading<List<FavouriteContent>>())
|
||||
|
||||
sut.get().test {
|
||||
expected.forEach { expectedItem ->
|
||||
Assertions.assertEquals(expectedItem, awaitItem())
|
||||
}
|
||||
Assertions.assertTrue(cancelAndConsumeRemainingEvents().isEmpty())
|
||||
}
|
||||
}
|
||||
|
||||
@DisplayName("GIVEN loading AND listOfFavourite WHEN observed THEN loading is shown")
|
||||
@Test
|
||||
fun loadingResourceWithFavouritesResultsInLoadingResource() = runTest {
|
||||
favouriteContentIdFlow.value = listOf(ContentId("a"))
|
||||
contentFlow.value = Resource.Loading()
|
||||
val expected = listOf(Resource.Loading<List<FavouriteContent>>())
|
||||
|
||||
sut.get().test {
|
||||
expected.forEach { expectedItem ->
|
||||
Assertions.assertEquals(expectedItem, awaitItem())
|
||||
}
|
||||
Assertions.assertTrue(cancelAndConsumeRemainingEvents().isEmpty())
|
||||
}
|
||||
}
|
||||
|
||||
@DisplayName("GIVEN error AND empty favourite WHEN observed THEN error is shown")
|
||||
@Test
|
||||
fun errorResourceWithNoFavouritesResultsInErrorResource() = runTest {
|
||||
favouriteContentIdFlow.value = emptyList()
|
||||
val exception = Throwable()
|
||||
contentFlow.value = Resource.Error(exception)
|
||||
val expected = listOf(Resource.Error<List<FavouriteContent>>(exception))
|
||||
|
||||
sut.get().test {
|
||||
expected.forEach { expectedItem ->
|
||||
Assertions.assertEquals(expectedItem, awaitItem())
|
||||
}
|
||||
Assertions.assertTrue(cancelAndConsumeRemainingEvents().isEmpty())
|
||||
}
|
||||
}
|
||||
|
||||
@DisplayName("GIVEN error AND listOfFavourite WHEN observed THEN error is shown")
|
||||
@Test
|
||||
fun errorResourceWithFavouritesResultsInErrorResource() = runTest {
|
||||
favouriteContentIdFlow.value = listOf(ContentId("b"))
|
||||
val exception = Throwable()
|
||||
contentFlow.value = Resource.Error(exception)
|
||||
val expected = listOf(Resource.Error<List<FavouriteContent>>(exception))
|
||||
|
||||
sut.get().test {
|
||||
expected.forEach { expectedItem ->
|
||||
Assertions.assertEquals(expectedItem, awaitItem())
|
||||
}
|
||||
Assertions.assertTrue(cancelAndConsumeRemainingEvents().isEmpty())
|
||||
}
|
||||
}
|
||||
|
||||
@DisplayName("GIVEN listOfContent AND empty favourite WHEN observed THEN favourites are returned")
|
||||
@Test
|
||||
fun successResourceWithNoFavouritesResultsInNoFavouritedItems() = runTest {
|
||||
favouriteContentIdFlow.value = emptyList()
|
||||
val content = Content(ContentId("a"), "b", "c", ImageUrl("d"))
|
||||
contentFlow.value = Resource.Success(listOf(content))
|
||||
val items = listOf(
|
||||
FavouriteContent(content, false)
|
||||
)
|
||||
val expected = listOf(Resource.Success(items))
|
||||
|
||||
sut.get().test {
|
||||
expected.forEach { expectedItem ->
|
||||
Assertions.assertEquals(expectedItem, awaitItem())
|
||||
}
|
||||
Assertions.assertTrue(cancelAndConsumeRemainingEvents().isEmpty())
|
||||
}
|
||||
}
|
||||
|
||||
@DisplayName("GIVEN listOfContent AND other favourite id WHEN observed THEN favourites are returned")
|
||||
@Test
|
||||
fun successResourceWithDifferentFavouritesResultsInNoFavouritedItems() = runTest {
|
||||
favouriteContentIdFlow.value = listOf(ContentId("x"))
|
||||
val content = Content(ContentId("a"), "b", "c", ImageUrl("d"))
|
||||
contentFlow.value = Resource.Success(listOf(content))
|
||||
val items = listOf(
|
||||
FavouriteContent(content, false)
|
||||
)
|
||||
val expected = listOf(Resource.Success(items))
|
||||
|
||||
sut.get().test {
|
||||
expected.forEach { expectedItem ->
|
||||
Assertions.assertEquals(expectedItem, awaitItem())
|
||||
}
|
||||
Assertions.assertTrue(cancelAndConsumeRemainingEvents().isEmpty())
|
||||
}
|
||||
}
|
||||
|
||||
@DisplayName("GIVEN listOfContent AND same favourite id WHEN observed THEN favourites are returned")
|
||||
@Test
|
||||
fun successResourceWithSameFavouritesResultsInFavouritedItems() = runTest {
|
||||
favouriteContentIdFlow.value = listOf(ContentId("a"))
|
||||
val content = Content(ContentId("a"), "b", "c", ImageUrl("d"))
|
||||
contentFlow.value = Resource.Success(listOf(content))
|
||||
val items = listOf(
|
||||
FavouriteContent(content, true)
|
||||
)
|
||||
val expected = listOf(Resource.Success(items))
|
||||
|
||||
sut.get().test {
|
||||
expected.forEach { expectedItem ->
|
||||
Assertions.assertEquals(expectedItem, awaitItem())
|
||||
}
|
||||
Assertions.assertTrue(cancelAndConsumeRemainingEvents().isEmpty())
|
||||
}
|
||||
}
|
||||
|
||||
@DisplayName("GIVEN loading then data then added favourite WHEN observed THEN loading then correct favourites are returned")
|
||||
@Test
|
||||
fun whileLoadingAndAddingItemsReactsProperly() = runTest {
|
||||
favouriteContentIdFlow.value = emptyList()
|
||||
val content = Content(ContentId("a"), "b", "c", ImageUrl("d"))
|
||||
contentFlow.value = Resource.Loading()
|
||||
val expected = listOf(
|
||||
Resource.Loading(),
|
||||
Resource.Success(listOf(FavouriteContent(content, false))),
|
||||
Resource.Success(listOf(FavouriteContent(content, true)))
|
||||
)
|
||||
|
||||
sut.get().test {
|
||||
contentFlow.value = Resource.Success(listOf(content))
|
||||
favouriteContentIdFlow.value = listOf(ContentId("a"))
|
||||
|
||||
expected.forEach { expectedItem ->
|
||||
Assertions.assertEquals(expectedItem, awaitItem())
|
||||
}
|
||||
Assertions.assertTrue(cancelAndConsumeRemainingEvents().isEmpty())
|
||||
}
|
||||
}
|
||||
|
||||
@DisplayName("GIVEN loading then data then removed favourite WHEN observed THEN loading then correct favourites are returned")
|
||||
@Test
|
||||
fun whileLoadingAndRemovingItemsReactsProperly() = runTest {
|
||||
favouriteContentIdFlow.value = listOf(ContentId("a"))
|
||||
val content = Content(ContentId("a"), "b", "c", ImageUrl("d"))
|
||||
contentFlow.value = Resource.Loading()
|
||||
val expected = listOf(
|
||||
Resource.Loading(),
|
||||
Resource.Success(listOf(FavouriteContent(content, true))),
|
||||
Resource.Success(listOf(FavouriteContent(content, false)))
|
||||
)
|
||||
|
||||
sut.get().test {
|
||||
contentFlow.value = Resource.Success(listOf(content))
|
||||
favouriteContentIdFlow.value = emptyList()
|
||||
|
||||
expected.forEach { expectedItem ->
|
||||
Assertions.assertEquals(expectedItem, awaitItem())
|
||||
}
|
||||
Assertions.assertTrue(cancelAndConsumeRemainingEvents().isEmpty())
|
||||
}
|
||||
}
|
||||
|
||||
@DisplayName("GIVEN loading then data then loading WHEN observed THEN loading then correct favourites then loading are returned")
|
||||
@Test
|
||||
fun loadingThenDataThenLoadingReactsProperly() = runTest {
|
||||
favouriteContentIdFlow.value = listOf(ContentId("a"))
|
||||
val content = Content(ContentId("a"), "b", "c", ImageUrl("d"))
|
||||
contentFlow.value = Resource.Loading()
|
||||
val expected = listOf(
|
||||
Resource.Loading(),
|
||||
Resource.Success(listOf(FavouriteContent(content, true))),
|
||||
Resource.Loading()
|
||||
)
|
||||
|
||||
sut.get().test {
|
||||
contentFlow.value = Resource.Success(listOf(content))
|
||||
contentFlow.value = Resource.Loading()
|
||||
|
||||
expected.forEach { expectedItem ->
|
||||
Assertions.assertEquals(expectedItem, awaitItem())
|
||||
}
|
||||
Assertions.assertTrue(cancelAndConsumeRemainingEvents().isEmpty())
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue