我想測驗以下方法:
@Transactional
override suspend fun updateDebtWithoutDocumentsByUserId(userId: Long, dtoIn: DebtDTO): DebtDTO {
if (dtoIn.id == null) {
throw NotFoundException("Can only update existing debt")
}
val d = debtRepository.findById(dtoIn.id) ?: throw NotFoundException("Could not find debt ${dtoIn.id}")
val updated = debtRepository.save(
d.copy(
title = dtoIn.title,
amount = dtoIn.amount,
category = dtoIn.category,
)
)
if (dtoIn.amount != d.amount) {
// update potentially existing installment plan.
// Note that this guarantees that the installment amount is kept in bounds and all installment records are updated
// accordingly.
val installmentPlan = installmentPlanRepository.findByDebtId(dtoIn.id)
if (installmentPlan != null) {
val installmentRecordIds: List<Long> = installmentRepository.findByDebtId(dtoIn.id)
.toList()
.map { it.recordId }
storeInstallmentPlan(dtoIn.id, InstallmentPlanDTO.from(installmentPlan, installmentRecordIds))
.collect() // ensure that the flow is executed.
}
}
val documents = debtDocumentRepository.findByDebtId(dtoIn.id)
.toSet()
.map { DocumentDTO.from(it) }
.associateBy { it.id!! }
return DebtDTO.from(updated, documents)
}
如果有可用的分期付款計劃,storeInstallmentPlan(dtoIn.id, InstallmentPlanDTO.from(installmentPlan, installmentRecordIds))則將呼叫該方法。原始方法storeInstallmentPlan已經過測驗。
如何storeInstallmentPlan在我想測驗的單元內模擬而不通過storeInstallmentPlan再次測驗來重復自己?我想我必須以某種方式使用SpyK它,但我不知道該怎么做。也許有人對我有解決方案。
謝謝 :)
這是我的完整測驗課程:
@ExtendWith(MockKExtension::class)
internal class PlanServiceFeatureImplTest {
@MockK
lateinit var debtRepository: DebtRepository
@MockK
lateinit var debtDocumentRepository: DebtDocumentRepository
@MockK
lateinit var installmentPlanRepository: InstallmentPlanRepository
@MockK
lateinit var installmentRepository: InstallmentRepository
@MockK
lateinit var recordService: RecordService
@MockK
lateinit var userService: UserService
@InjectMockKs
lateinit var planService: PlanServiceFeatureImpl
@Test
fun `updateDebtWithoutDocumentsByUserId ok - no installment plan available`() {
val userId = 123L
val dtoIn = DebtDTO(
id = 1L,
title = "debt1New",
amount = BigDecimal.valueOf(2000),
category = DebtCategory.dangerous,
documents = mapOf(),
)
val oldDebt = Debt(
id = 1L,
userId = userId,
title = "debt1",
amount = BigDecimal.valueOf(1000),
category = DebtCategory.credit,
)
assertThat(dtoIn.title).isNotEqualTo(oldDebt.title)
assertThat(dtoIn.amount).isNotEqualTo(oldDebt.amount)
assertThat(dtoIn.category).isNotEqualTo(oldDebt.category)
coEvery { debtRepository.findById(dtoIn.id!!) } returns oldDebt
val doc1 = DebtDocument(
id = 11L,
debtId = dtoIn.id!!,
title = "doc1",
bytes = byteArrayOf(0x01),
)
coEvery { debtRepository.save(any()) } answers { arg(0) }
coEvery { debtDocumentRepository.findByDebtId(dtoIn.id!!) } returns flowOf(doc1)
//no installment plan available
coEvery { installmentPlanRepository.findByDebtId(dtoIn.id!!) } returns null
runBlocking {
val actual = planService.updateDebtWithoutDocumentsByUserId(userId, dtoIn)
assertThat(actual).isEqualTo(
dtoIn.copy(
documents = mapOf(doc1.id!! to DocumentDTO.from(doc1)),
)
)
}
coVerify {
debtRepository.save(withArg {
assertThat(it.id).isEqualTo(dtoIn.id)
assertThat(it.userId).isEqualTo(userId)
assertThat(it.title).isEqualTo(dtoIn.title)
assertThat(it.amount).isEqualTo(dtoIn.amount)
assertThat(it.category).isEqualTo(dtoIn.category)
})
}
}
@Test
fun `updateDebtWithoutDocumentsByUserId ok - installment plan available`() {
val userId = 123L
val dtoIn = DebtDTO(
id = 1L,
title = "debt1New",
amount = BigDecimal.valueOf(2000),
category = DebtCategory.dangerous,
documents = mapOf(),
)
val oldDebt = Debt(
id = 1L,
userId = userId,
title = "debt1",
amount = BigDecimal.valueOf(1000),
category = DebtCategory.credit,
)
assertThat(dtoIn.title).isNotEqualTo(oldDebt.title)
assertThat(dtoIn.amount).isNotEqualTo(oldDebt.amount)
assertThat(dtoIn.category).isNotEqualTo(oldDebt.category)
coEvery { debtRepository.findById(dtoIn.id!!) } returns oldDebt
val doc1 = DebtDocument(
id = 11L,
debtId = dtoIn.id!!,
title = "doc1",
bytes = byteArrayOf(0x01),
)
coEvery { debtRepository.save(any()) } answers { arg(0) }
coEvery { debtDocumentRepository.findByDebtId(dtoIn.id!!) } returns flowOf(doc1)
//installment plan available
val plan = mockk<InstallmentPlan>()
coEvery { installmentPlanRepository.findByDebtId(dtoIn.id!!) } returns plan
coEvery { installmentRepository.findByDebtId(dtoIn.id!!) } returns flowOf()
/*
Here I need to test storeInstallmentPlan / mock of it
*/
runBlocking {
val actual = planService.updateDebtWithoutDocumentsByUserId(userId, dtoIn)
assertThat(actual).isEqualTo(
dtoIn.copy(
documents = mapOf(doc1.id!! to DocumentDTO.from(doc1)),
)
)
}
coVerify {
debtRepository.save(withArg {
assertThat(it.id).isEqualTo(dtoIn.id)
assertThat(it.userId).isEqualTo(userId)
assertThat(it.title).isEqualTo(dtoIn.title)
assertThat(it.amount).isEqualTo(dtoIn.amount)
assertThat(it.category).isEqualTo(dtoIn.category)
})
}
}
@Test
fun `storeInstallmentPlan ok`(@MockK user: User) {
val debtId = 123L
val debtAmount = BigDecimal.valueOf(1000)
val installmentAmount = BigDecimal.valueOf(500)
val interval = Repeat.monthly
val firstPaymentDate = LocalDate.of(2021, 12, 27)
.atStartOfDay(Time.DEFAULT_TIME_ZONE).toOffsetDateTime()
val planDTO = InstallmentPlanDTO(
interval = interval,
firstPaymentDate = firstPaymentDate,
amount = installmentAmount,
installments = listOf()
)
val debt = Debt(
userId = 32L,
title = "debt1",
amount = debtAmount,
category = DebtCategory.credit
)
val plan = InstallmentPlan(
id = 122L,
debtId = debtId,
interval = interval,
firstPaymentDate = firstPaymentDate,
amount = installmentAmount
)
val installment1 = Installment(
id = 12L,
debtId = debtId,
recordId = 15L
)
val installment2 = Installment(
id = 13L,
debtId = debtId,
recordId = 16L
)
val installments = listOf(
WalletRecord(
userId = debt.userId,
type = RecordType.debt_rate,
amount = installmentAmount,
title = debt.title,
category = RecordCategory.debt_rate,
repeat = plan.interval,
startDate = ZonedDateTime.parse("2021-11-28T00:00 01:00[Europe/Berlin]").toOffsetDateTime(),
endDate = ZonedDateTime.parse("2021-12-27T00:00 01:00[Europe/Berlin]").toOffsetDateTime()
),
WalletRecord(
userId = debt.userId,
type = RecordType.debt_rate,
amount = installmentAmount,
title = debt.title,
category = RecordCategory.debt_rate,
repeat = plan.interval,
startDate = ZonedDateTime.parse("2021-12-28T00:00 01:00[Europe/Berlin]").toOffsetDateTime(),
endDate = ZonedDateTime.parse("2022-01-27T00:00 01:00[Europe/Berlin]").toOffsetDateTime()
)
)
every { user.tz } returns "Europe/Berlin"
coEvery { debtRepository.findById(debtId) } returns debt
//installment plan for debt with debtId exists
coEvery { installmentPlanRepository.findByDebtId(debtId) } returns plan
//update installment plan
coEvery {
installmentPlanRepository.save(planDTO.copy(amount = installmentAmount).toEntity(id = plan.id, debtId = debtId))
} returns InstallmentPlan(plan.id, debtId, interval, firstPaymentDate, installmentAmount)
//find and delete all previous installments/records for debt with debtId
coEvery { installmentRepository.findByDebtId(debtId) } returns flowOf(installment1, installment2)
coEvery { installmentRepository.deleteAllById(listOf(installment1.id!!, installment2.id!!)) } just Runs
coEvery { recordService.deleteAll(listOf(installment1.recordId, installment2.recordId)) } just Runs
//replace all new installments/records
coEvery { userService.findById(debt.userId) } returns user
coEvery { recordService.saveAll(installments) } returns flowOf()
coEvery { installmentRepository.saveAll(any<Flow<Installment>>()) } returns flowOf()
runBlocking { planService.storeInstallmentPlan(debtId, planDTO) }
coVerify { installmentPlanRepository.save(
planDTO.copy(amount = installmentAmount).toEntity(id = plan.id, debtId = debtId)
) }
coVerify { recordService.saveAll(installments) }
coVerify { installmentRepository.saveAll(any<Flow<Installment>>()) }
}
}
uj5u.com熱心網友回復:
假設這storeInstallmentPlan()是公開的,那么您可以使用@SpyK您正在測驗的類進行注釋,然后您需要storeInstallmentPlan()在updateDebtWithoutDocumentsByUserId ok - no installment plan available測驗中模擬呼叫。
如果您可以添加完整的測驗類,那么我們可以提供一個完整的示例。
uj5u.com熱心網友回復:
如何通過再次測驗 storeInstallmentPlan 在我想測驗的單元內模擬 storeInstallmentPlan 而不會重復自己?
您可以監視被測實體。偽代碼:
@Test
fun myTest() {
val objectUnderTest = createTestObject()
val spy = spyk(objectUnderTest)
// Set up mocks used internally, etc
spy.updateDebtWithoutDocumentsByUserId() // Call method on spy
verify { spy.storeInstallmentPlan(...) }
}
如果storeInstallmentPlan尚未公開,您可以使用@VisibileForTesting.
或者,考慮在計劃存在時測驗呼叫方法的結果。當計劃存在時,您可以觀察到呼叫該方法的預期結果有哪些副作用?
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/406799.html
標籤:
上一篇:當使用Mockito.spy()模擬一個方法被另一個方法呼叫時,為什么我會得到一個UnnecessaryStubbingException?
