From f8d1f407ff2d0e985300f6f19184793b64250a1d Mon Sep 17 00:00:00 2001 From: Jonathan Rodrigues Date: Mon, 6 May 2024 00:39:16 -0300 Subject: [PATCH] Added unit tests --- .../domain/mapper/HomeModelToUiMapperTest.kt | 20 ++- .../stocks/domain/types/StockAlertTypeTest.kt | 28 ++++ .../domain/types/StockStatusTypeTest.kt | 28 ++++ .../domain/usecase/StockAlertUseCaseTest.kt | 147 ++++++++++++++++++ .../repository/StockRepositoryImplTest.kt | 117 ++++++++++++++ 5 files changed, 336 insertions(+), 4 deletions(-) create mode 100644 feature/stocks/src/test/kotlin/br/com/stonks/feature/stocks/domain/types/StockAlertTypeTest.kt create mode 100644 feature/stocks/src/test/kotlin/br/com/stonks/feature/stocks/domain/types/StockStatusTypeTest.kt create mode 100644 feature/stocks/src/test/kotlin/br/com/stonks/feature/stocks/domain/usecase/StockAlertUseCaseTest.kt create mode 100644 feature/stocks/src/test/kotlin/br/com/stonks/feature/stocks/repository/StockRepositoryImplTest.kt diff --git a/feature/home/src/test/kotlin/br/com/stonks/feature/home/domain/mapper/HomeModelToUiMapperTest.kt b/feature/home/src/test/kotlin/br/com/stonks/feature/home/domain/mapper/HomeModelToUiMapperTest.kt index 2bb04fb..d668109 100644 --- a/feature/home/src/test/kotlin/br/com/stonks/feature/home/domain/mapper/HomeModelToUiMapperTest.kt +++ b/feature/home/src/test/kotlin/br/com/stonks/feature/home/domain/mapper/HomeModelToUiMapperTest.kt @@ -14,6 +14,8 @@ import br.com.stonks.feature.home.ui.model.DailyTransactionUiModel import br.com.stonks.feature.home.ui.model.HomeUiModel import br.com.stonks.feature.home.ui.model.PortfolioUiModel import br.com.stonks.feature.home.ui.model.TransactionUiModel +import io.mockk.every +import io.mockk.mockk import org.junit.Assert.assertEquals import org.junit.Test import java.util.Date @@ -21,21 +23,26 @@ import java.util.Date class HomeModelToUiMapperTest { private val currentDate = Date(2024, 4, 3) - private val sut = HomeModelToUiMapper() + private val walletModelToChartMapper = mockk() + private val sut = HomeModelToUiMapper(walletModelToChartMapper) @Test fun `given model when call mapper then convert to ui model`() { + every { + walletModelToChartMapper.mapper(any()) + } returns createPieChartData() + val expected = createResultData() val result = sut.mapper(createInputData()) assertEquals(expected, result) } - private fun createResultData() = HomeUiModel( - totalAssets = 1.0, - portfolioChart = PieChartData( + private fun createPieChartData() = listOf( + PieChartData( title = "Todos os produtos", value = 1.0, + progress = 1f, dataProgress = listOf( PieChartDataProgress( progress = 0.5f, @@ -43,6 +50,11 @@ class HomeModelToUiMapperTest { ), ), ), + ) + + private fun createResultData() = HomeUiModel( + totalAssets = 1.0, + portfolioChart = createPieChartData(), portfolio = listOf( PortfolioUiModel( tagColor = ColorToken.HighlightOrange, diff --git a/feature/stocks/src/test/kotlin/br/com/stonks/feature/stocks/domain/types/StockAlertTypeTest.kt b/feature/stocks/src/test/kotlin/br/com/stonks/feature/stocks/domain/types/StockAlertTypeTest.kt new file mode 100644 index 0000000..61618f8 --- /dev/null +++ b/feature/stocks/src/test/kotlin/br/com/stonks/feature/stocks/domain/types/StockAlertTypeTest.kt @@ -0,0 +1,28 @@ +package br.com.stonks.feature.stocks.domain.types + +import org.junit.Assert +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.Parameterized + +@RunWith(Parameterized::class) +internal class StockAlertTypeTest( + private val input: String, + private val expected: StockAlertType, +) { + + companion object { + @JvmStatic + @Parameterized.Parameters + fun arguments(): List> = listOf( + arrayOf("unknown", StockAlertType.UNKNOWN), + arrayOf("high", StockAlertType.HIGH_PRICE), + arrayOf("low", StockAlertType.LOW_PRICE), + ) + } + + @Test + fun `given type string when convert to enum return a mapped type`() { + Assert.assertEquals(expected, StockAlertType.fromString(input)) + } +} diff --git a/feature/stocks/src/test/kotlin/br/com/stonks/feature/stocks/domain/types/StockStatusTypeTest.kt b/feature/stocks/src/test/kotlin/br/com/stonks/feature/stocks/domain/types/StockStatusTypeTest.kt new file mode 100644 index 0000000..10759c5 --- /dev/null +++ b/feature/stocks/src/test/kotlin/br/com/stonks/feature/stocks/domain/types/StockStatusTypeTest.kt @@ -0,0 +1,28 @@ +package br.com.stonks.feature.stocks.domain.types + +import org.junit.Assert.assertEquals +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.Parameterized + +@RunWith(Parameterized::class) +internal class StockStatusTypeTest( + private val input: String, + private val expected: StockStatusType, +) { + + companion object { + @JvmStatic + @Parameterized.Parameters + fun arguments(): List> = listOf( + arrayOf("unknown", StockStatusType.UNKNOWN), + arrayOf("available", StockStatusType.AVAILABLE), + arrayOf("unavailable", StockStatusType.UNAVAILABLE), + ) + } + + @Test + fun `given type string when convert to enum return a mapped type`() { + assertEquals(expected, StockStatusType.fromString(input)) + } +} diff --git a/feature/stocks/src/test/kotlin/br/com/stonks/feature/stocks/domain/usecase/StockAlertUseCaseTest.kt b/feature/stocks/src/test/kotlin/br/com/stonks/feature/stocks/domain/usecase/StockAlertUseCaseTest.kt new file mode 100644 index 0000000..02f5bb8 --- /dev/null +++ b/feature/stocks/src/test/kotlin/br/com/stonks/feature/stocks/domain/usecase/StockAlertUseCaseTest.kt @@ -0,0 +1,147 @@ +package br.com.stonks.feature.stocks.domain.usecase + +import br.com.stonks.common.db.DefaultPrimaryKey +import br.com.stonks.feature.stocks.domain.mapper.StockAlertModelToResponseMapper +import br.com.stonks.feature.stocks.domain.mapper.StockAlertResponseToModelMapper +import br.com.stonks.feature.stocks.domain.model.StockAlertModel +import br.com.stonks.feature.stocks.domain.types.StockAlertType +import br.com.stonks.feature.stocks.domain.types.StockStatusType +import br.com.stonks.feature.stocks.repository.StockRepository +import br.com.stonks.feature.stocks.repository.remote.response.StockAlertResponse +import br.com.stonks.testing.rules.CoroutinesTestRule +import io.mockk.coEvery +import io.mockk.coVerify +import io.mockk.coVerifyOrder +import io.mockk.every +import io.mockk.mockk +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.test.runTest +import org.junit.Rule +import org.junit.Test + +@OptIn(ExperimentalCoroutinesApi::class) +class StockAlertUseCaseTest { + + @get:Rule + var coroutinesTestRule = CoroutinesTestRule() + + private val stockRepositoryMock = mockk() + private val stockPriceComparatorUseCaseMock = mockk() + private val stockAlertModelMapperMock = mockk() + private val stockAlertResponseMapperMock = mockk() + + private val sut = StockAlertUseCase( + stockRepository = stockRepositoryMock, + stockPriceComparatorUseCase = stockPriceComparatorUseCaseMock, + stockAlertModelMapper = stockAlertModelMapperMock, + stockAlertResponseMapper = stockAlertResponseMapperMock, + ) + + @Test + fun `given use case when call local alerts then check price comparator and mapper to model`() = runTest { + val fakeResponse = createFakeResponse() + + coEvery { + stockRepositoryMock.listStockAlerts() + } returns Result.success(listOf(fakeResponse)) + + coEvery { + stockPriceComparatorUseCaseMock.checkStockPrice(fakeResponse) + } returns StockAlertType.HIGH_PRICE + + sut.listStockAlerts() + + coVerifyOrder { + stockPriceComparatorUseCaseMock.checkStockPrice( + fakeResponse + ) + stockAlertModelMapperMock.mapper( + createFakeResponse(trigger = StockAlertType.HIGH_PRICE.status) + ) + } + } + + @Test + fun `given save alert when use default primary key then call insert method`() = runTest { + val fakeAlert = createFakeAlert() + val fakeResponse = createFakeResponse() + + every { + stockAlertResponseMapperMock.mapper(fakeAlert) + } returns fakeResponse + + coEvery { + stockRepositoryMock.insertStockAlert(fakeResponse) + } returns mockk() + + sut.saveStockAlert(fakeAlert) + + coVerify(exactly = 1) { + stockRepositoryMock.insertStockAlert(fakeResponse) + } + + coVerify(exactly = 0) { + stockRepositoryMock.updateStockAlert(any()) + } + } + + @Test + fun `given save alert when use generated key then call update method`() = runTest { + val fakeAlert = createFakeAlert(id = 5L) + val fakeResponse = createFakeResponse(id = 5L) + + every { + stockAlertResponseMapperMock.mapper(fakeAlert) + } returns fakeResponse + + coEvery { + stockRepositoryMock.updateStockAlert(fakeResponse) + } returns Result.success(mockk()) + + sut.saveStockAlert(fakeAlert) + + coVerify(exactly = 1) { + stockRepositoryMock.updateStockAlert(fakeResponse) + } + + coVerify(exactly = 0) { + stockRepositoryMock.insertStockAlert(any()) + } + } + + @Test + fun `given use case when call delete stock then call delete method`() = runTest { + val alertId = 1L + + coEvery { + stockRepositoryMock.deleteStockAlert(alertId) + } returns mockk() + + sut.deleteStockAlert(alertId) + + coVerify { + stockRepositoryMock.deleteStockAlert(alertId) + } + } + + private fun createFakeAlert( + id: Long = DefaultPrimaryKey, + ) = StockAlertModel( + id = id, + ticket = "lorem", + alertValue = 1.0, + status = StockStatusType.AVAILABLE, + notificationTrigger = StockAlertType.HIGH_PRICE, + ) + + private fun createFakeResponse( + id: Long = DefaultPrimaryKey, + trigger: String = "unknown", + ) = StockAlertResponse( + id = id, + stockTicket = "lorem", + alertValue = 5.0, + status = "available", + notificationTrigger = trigger, + ) +} diff --git a/feature/stocks/src/test/kotlin/br/com/stonks/feature/stocks/repository/StockRepositoryImplTest.kt b/feature/stocks/src/test/kotlin/br/com/stonks/feature/stocks/repository/StockRepositoryImplTest.kt new file mode 100644 index 0000000..7d32e45 --- /dev/null +++ b/feature/stocks/src/test/kotlin/br/com/stonks/feature/stocks/repository/StockRepositoryImplTest.kt @@ -0,0 +1,117 @@ +package br.com.stonks.feature.stocks.repository + +import br.com.stonks.feature.stocks.domain.mapper.StockAlertEntityToResponseMapper +import br.com.stonks.feature.stocks.domain.mapper.StockAlertResponseToEntityMapper +import br.com.stonks.feature.stocks.repository.local.StockAlertEntity +import br.com.stonks.feature.stocks.repository.local.StockLocalDataSource +import br.com.stonks.feature.stocks.repository.remote.StockRemoteDataSource +import br.com.stonks.feature.stocks.repository.remote.response.StockAlertResponse +import io.mockk.coEvery +import io.mockk.coVerify +import io.mockk.coVerifyOrder +import io.mockk.mockk +import kotlinx.coroutines.test.runTest +import org.junit.Test + +class StockRepositoryImplTest { + + private val fakeEntity = mockk() + private val fakeResponse = mockk() + private val stockRemoteDataSourceMock = mockk(relaxed = true) + private val stockLocalDataSourceMock = mockk(relaxed = true) + private val stockAlertResponseMapperMock = mockk(relaxed = true) + private val stockAlertEntityMapperMock = mockk(relaxed = true) + + private val sut = StockRepositoryImpl( + stockRemoteDataSource = stockRemoteDataSourceMock, + stockLocalDataSource = stockLocalDataSourceMock, + stockAlertResponseMapper = stockAlertResponseMapperMock, + stockAlertEntityMapper = stockAlertEntityMapperMock, + ) + + @Test + fun `given repository when get remote alerts then call remote data source`() = runTest { + sut.getRemoteStockAlerts() + + coVerify { stockRemoteDataSourceMock.getStockAlerts() } + } + + @Test + fun `given repository when get local alerts then call local data source`() = runTest { + coEvery { + stockLocalDataSourceMock.listStockAlerts() + } returns Result.success(listOf(fakeEntity)) + + sut.listStockAlerts() + + coVerifyOrder { + stockLocalDataSourceMock.listStockAlerts() + stockAlertResponseMapperMock.mapper(fakeEntity) + } + } + + @Test + fun `given repository when get alert then call local data source`() = runTest { + val alertId = 1L + + coEvery { + stockLocalDataSourceMock.getStockAlert(alertId) + } returns Result.success(fakeEntity) + + sut.getStockAlert(alertId) + + coVerifyOrder { + stockLocalDataSourceMock.getStockAlert(alertId) + stockAlertResponseMapperMock.mapper(fakeEntity) + } + } + + @Test + fun `given repository when insert alert then call local data source`() = runTest { + coEvery { + stockAlertEntityMapperMock.mapper(fakeResponse) + } returns fakeEntity + + coEvery { + stockLocalDataSourceMock.insertStockAlert(fakeEntity) + } returns mockk() + + sut.insertStockAlert(fakeResponse) + + coVerify { + stockLocalDataSourceMock.insertStockAlert(fakeEntity) + } + } + + @Test + fun `given repository when update alert then call local data source`() = runTest { + coEvery { + stockAlertEntityMapperMock.mapper(fakeResponse) + } returns fakeEntity + + coEvery { + stockLocalDataSourceMock.updateStockAlert(fakeEntity) + } returns mockk() + + sut.updateStockAlert(fakeResponse) + + coVerify { + stockLocalDataSourceMock.updateStockAlert(fakeEntity) + } + } + + @Test + fun `given repository when delete alert then call local data source`() = runTest { + val alertId = 1L + + coEvery { + stockLocalDataSourceMock.deleteStockAlert(alertId) + } returns mockk() + + sut.deleteStockAlert(alertId) + + coVerify { + stockLocalDataSourceMock.deleteStockAlert(alertId) + } + } +}