#25 Migrate mix types to new logic

This commit is contained in:
FyloZ 2022-03-06 19:12:57 -05:00
parent 618ef6c77a
commit 956db504f5
Signed by: william
GPG Key ID: 835378AE9AF4AE97
8 changed files with 264 additions and 337 deletions

View File

@ -0,0 +1,9 @@
package dev.fyloz.colorrecipesexplorer.dtos
data class MixTypeDto(
override val id: Long = 0L,
val name: String,
val material: MaterialDto
) : EntityDto

View File

@ -49,13 +49,13 @@ class DefaultMixLogic(
override fun save(entity: MixSaveDto): Mix {
val recipe = recipeLogic.getById(entity.recipeId)
val materialType = materialTypeLogic.getById(entity.materialTypeId)
val mixType = mixTypeLogic.getOrCreateForNameAndMaterialType(entity.name, materialType(materialType))
val mixType = mixTypeLogic.getOrCreateForNameAndMaterialType(entity.name, materialType)
val mixMaterials =
if (entity.mixMaterials != null) mixMaterialLogic.saveAll(entity.mixMaterials).toSet() else setOf()
mixMaterialLogic.validateMixMaterials(mixMaterials)
var mix = mix(recipe = recipe, mixType = mixType, mixMaterials = mixMaterials.map(::mixMaterial).toMutableSet())
var mix = mix(recipe = recipe, mixType = mixType(mixType), mixMaterials = mixMaterials.map(::mixMaterial).toMutableSet())
mix = save(mix)
recipeLogic.addMix(recipe, mix)
@ -74,9 +74,9 @@ class DefaultMixLogic(
mix.mixType.material.materialType!!
mix.mixType = if (mixTypeIsShared(mix.mixType)) {
mixTypeLogic.saveForNameAndMaterialType(name, materialType)
mixType(mixTypeLogic.saveForNameAndMaterialType(name, materialTypeDto(materialType)))
} else {
mixTypeLogic.updateForNameAndMaterialType(mix.mixType, name, materialType)
mixType(mixTypeLogic.updateForNameAndMaterialType(mixTypeDto(mix.mixType), name, materialTypeDto(materialType)))
}
}
if (entity.mixMaterials != null) {

View File

@ -1,84 +1,58 @@
package dev.fyloz.colorrecipesexplorer.logic
import dev.fyloz.colorrecipesexplorer.config.annotations.RequireDatabase
import dev.fyloz.colorrecipesexplorer.exception.AlreadyExistsException
import dev.fyloz.colorrecipesexplorer.model.*
import dev.fyloz.colorrecipesexplorer.repository.MixTypeRepository
import org.springframework.context.annotation.Lazy
import org.springframework.stereotype.Service
import dev.fyloz.colorrecipesexplorer.config.annotations.LogicComponent
import dev.fyloz.colorrecipesexplorer.dtos.MaterialDto
import dev.fyloz.colorrecipesexplorer.dtos.MaterialTypeDto
import dev.fyloz.colorrecipesexplorer.dtos.MixTypeDto
import dev.fyloz.colorrecipesexplorer.model.MixType
import dev.fyloz.colorrecipesexplorer.service.MixTypeService
import org.springframework.transaction.annotation.Transactional
interface MixTypeLogic : NamedModelService<MixType, MixTypeRepository> {
/** Checks if a [MixType] with the given [name] and [materialType] exists. */
fun existsByNameAndMaterialType(name: String, materialType: MaterialType): Boolean
/** Gets the mix type with the given [material]. */
fun getByMaterial(material: Material): MixType
/** Gets the [MixType] with the given [name] and [materialType]. */
fun getByNameAndMaterialType(name: String, materialType: MaterialType): MixType
/** Returns a [MixType] for the given [name] and [materialType]. If a mix type with these does not already exists, it will be created. */
fun getOrCreateForNameAndMaterialType(name: String, materialType: MaterialType): MixType
interface MixTypeLogic : Logic<MixTypeDto, MixTypeService> {
/** Returns a [MixType] for the given [name] and [materialType]. If this mix type does not already exist, it will be created. */
fun getOrCreateForNameAndMaterialType(name: String, materialType: MaterialTypeDto): MixTypeDto
/** Returns a new and persisted [MixType] with the given [name] and [materialType]. */
fun saveForNameAndMaterialType(name: String, materialType: MaterialType): MixType
fun saveForNameAndMaterialType(name: String, materialType: MaterialTypeDto): MixTypeDto
/** Returns the given [mixType] updated with the given [name] and [materialType]. */
fun updateForNameAndMaterialType(mixType: MixType, name: String, materialType: MaterialType): MixType
fun updateForNameAndMaterialType(mixType: MixTypeDto, name: String, materialType: MaterialTypeDto): MixTypeDto
}
@Service
@RequireDatabase
class DefaultMixTypeLogic(
mixTypeRepository: MixTypeRepository,
@Lazy val materialLogic: MaterialLogic
) :
AbstractNamedModelService<MixType, MixTypeRepository>(mixTypeRepository), MixTypeLogic {
override fun idNotFoundException(id: Long) = mixTypeIdNotFoundException(id)
override fun idAlreadyExistsException(id: Long) = mixTypeIdAlreadyExistsException(id)
override fun nameNotFoundException(name: String) = mixTypeNameNotFoundException(name)
override fun nameAlreadyExistsException(name: String) = mixTypeNameAlreadyExistsException(name)
@LogicComponent
class DefaultMixTypeLogic(service: MixTypeService, private val materialLogic: MaterialLogic) :
BaseLogic<MixTypeDto, MixTypeService>(service, MixType::class.simpleName!!), MixTypeLogic {
override fun getOrCreateForNameAndMaterialType(name: String, materialType: MaterialTypeDto) =
service.getByNameAndMaterialType(name, materialType.id) ?: saveForNameAndMaterialType(name, materialType)
override fun existsByNameAndMaterialType(name: String, materialType: MaterialType): Boolean =
repository.existsByNameAndMaterialType(name, materialType)
override fun getByMaterial(material: Material): MixType =
repository.findByMaterial(material) ?: throw nameNotFoundException(material.name)
override fun getByNameAndMaterialType(name: String, materialType: MaterialType): MixType =
repository.findByNameAndMaterialType(name, materialType)
?: throw MixTypeNameAndMaterialTypeNotFoundException(name, materialType)
override fun getOrCreateForNameAndMaterialType(name: String, materialType: MaterialType): MixType =
if (existsByNameAndMaterialType(name, materialType))
getByNameAndMaterialType(name, materialType)
else
saveForNameAndMaterialType(name, materialType)
override fun save(entity: MixType): MixType {
if (materialLogic.existsByName(entity.name))
throw AlreadyExistsException("material", "material already exists", "material already exists details (TODO)", entity.name) // TODO
return super.save(entity)
}
override fun saveForNameAndMaterialType(name: String, materialType: MaterialType): MixType =
save(
mixType(
@Transactional
override fun saveForNameAndMaterialType(name: String, materialType: MaterialTypeDto): MixTypeDto {
val material = materialLogic.save(
MaterialDto(
name = name,
material = material(
name = name,
inventoryQuantity = Float.MIN_VALUE,
isMixType = true,
materialType = materialType
)
inventoryQuantity = Float.MIN_VALUE,
isMixType = true,
materialType = materialType
)
)
override fun updateForNameAndMaterialType(mixType: MixType, name: String, materialType: MaterialType): MixType =
update(mixType.copy(material = mixType.material.copy(name = name, materialType = materialType)))
override fun delete(entity: MixType) {
if (!repository.canBeDeleted(entity.id!!)) throw cannotDeleteMixTypeException(entity)
super.delete(entity)
return save(MixTypeDto(name = name, material = material))
}
}
override fun updateForNameAndMaterialType(
mixType: MixTypeDto,
name: String,
materialType: MaterialTypeDto
): MixTypeDto {
val material = materialLogic.update(mixType.material.copy(name = name, materialType = materialType))
return update(mixType.copy(name = name, material = material))
}
override fun deleteById(id: Long) {
if (service.isUsedByMixes(id)) {
throw cannotDeleteException("Cannot delete the mix type with the id '$id' because one or more mixes depends on it")
}
super.deleteById(id)
}
}

View File

@ -1,5 +1,6 @@
package dev.fyloz.colorrecipesexplorer.model
import dev.fyloz.colorrecipesexplorer.dtos.MixTypeDto
import dev.fyloz.colorrecipesexplorer.exception.AlreadyExistsException
import dev.fyloz.colorrecipesexplorer.exception.CannotDeleteException
import dev.fyloz.colorrecipesexplorer.exception.NotFoundException
@ -10,91 +11,42 @@ import javax.persistence.*
@Entity
@Table(name = "mix_type")
data class MixType(
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
override val id: Long?,
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
override val id: Long?,
@Column(unique = true)
override var name: String,
@Column(unique = true)
val name: String,
@OneToOne(cascade = [CascadeType.ALL])
@JoinColumn(name = "material_id")
var material: Material
) : NamedModelEntity
@OneToOne(cascade = [CascadeType.ALL])
@JoinColumn(name = "material_id")
var material: Material
) : ModelEntity
// ==== DSL ====
fun mixType(
id: Long? = null,
name: String = "name",
material: Material = material(),
op: MixType.() -> Unit = {}
id: Long? = null,
name: String = "name",
material: Material = material(),
op: MixType.() -> Unit = {}
) = MixType(id, name, material).apply(op)
fun mixType(
name: String = "name",
materialType: MaterialType = materialType(),
op: MixType.() -> Unit = {}
name: String = "name",
materialType: MaterialType = materialType(),
op: MixType.() -> Unit = {}
) = mixType(
id = null,
name,
material = material(name = name, inventoryQuantity = 0f, isMixType = true, materialType = materialType)
id = null,
name,
material = material(name = name, inventoryQuantity = 0f, isMixType = true, materialType = materialType)
).apply(op)
// ==== Exceptions ====
private const val MIX_TYPE_NOT_FOUND_EXCEPTION_TITLE = "Mix type not found"
private const val MIX_TYPE_ALREADY_EXISTS_EXCEPTION_TITLE = "Mix type already exists"
private const val MIX_TYPE_CANNOT_DELETE_EXCEPTION_TITLE = "Cannot delete mix type"
private const val MIX_TYPE_EXCEPTION_ERROR_CODE = "mixtype"
@Deprecated("Temporary DSL for transition")
fun mixTypeDto(
entity: MixType
) = MixTypeDto(entity.id!!, entity.name, materialDto(entity.material))
class MixTypeNameAndMaterialTypeNotFoundException(name: String, materialType: MaterialType) :
RestException(
"notfound-mixtype-namematerialtype",
MIX_TYPE_NOT_FOUND_EXCEPTION_TITLE,
HttpStatus.NOT_FOUND,
"A mix type with the name $name and material type ${materialType.name} could not be found",
mapOf(
"name" to name,
"materialType" to materialType.name
)
)
fun mixTypeIdNotFoundException(id: Long) =
NotFoundException(
MIX_TYPE_EXCEPTION_ERROR_CODE,
MIX_TYPE_NOT_FOUND_EXCEPTION_TITLE,
"A mix type with the id $id could not be found",
id
)
fun mixTypeIdAlreadyExistsException(id: Long) =
AlreadyExistsException(
MIX_TYPE_EXCEPTION_ERROR_CODE,
MIX_TYPE_ALREADY_EXISTS_EXCEPTION_TITLE,
"A mix type with the id $id already exists",
id
)
fun mixTypeNameNotFoundException(name: String) =
NotFoundException(
MIX_TYPE_EXCEPTION_ERROR_CODE,
MIX_TYPE_NOT_FOUND_EXCEPTION_TITLE,
"A mix type with the name $name could not be found",
name,
"name"
)
fun mixTypeNameAlreadyExistsException(name: String) =
AlreadyExistsException(
MIX_TYPE_EXCEPTION_ERROR_CODE,
MIX_TYPE_ALREADY_EXISTS_EXCEPTION_TITLE,
"A mix type with the name $name already exists",
name,
"name"
)
fun cannotDeleteMixTypeException(mixType: MixType) =
CannotDeleteException(
MIX_TYPE_EXCEPTION_ERROR_CODE,
MIX_TYPE_CANNOT_DELETE_EXCEPTION_TITLE,
"Cannot delete the mix type ${mixType.name} because one or more mixes depends on it"
)
@Deprecated("Temporary DSL for transition")
fun mixType(
dto: MixTypeDto
) = MixType(dto.id, dto.name, material(dto.material))

View File

@ -1,30 +1,27 @@
package dev.fyloz.colorrecipesexplorer.repository
import dev.fyloz.colorrecipesexplorer.model.Material
import dev.fyloz.colorrecipesexplorer.model.MaterialType
import dev.fyloz.colorrecipesexplorer.model.MixType
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.data.jpa.repository.Query
import org.springframework.stereotype.Repository
@Repository
interface MixTypeRepository : NamedJpaRepository<MixType> {
@Query("select case when(count(m) > 0) then true else false end from MixType m where m.name = :name and m.material.materialType = :materialType")
fun existsByNameAndMaterialType(name: String, materialType: MaterialType): Boolean
interface MixTypeRepository : JpaRepository<MixType, Long> {
/** Checks if a mix type with the given [name], [materialTypeId] and a different [id] exists. */
@Query("select case when(count(m) > 0) then true else false end from MixType m where m.name = :name and m.material.materialType.id = :materialTypeId and m.id <> :id")
fun existsByNameAndMaterialType(name: String, materialTypeId: Long, id: Long): Boolean
/** Gets the mix type with the given [material]. */
fun findByMaterial(material: Material): MixType?
/** Gets the [MixType] with the given [name] and [materialType]. */
@Query("select m from MixType m where m.name = :name and m.material.materialType = :materialType")
fun findByNameAndMaterialType(name: String, materialType: MaterialType): MixType?
/** Finds the mix type with the given [name] and [materialTypeId]. */
@Query("select m from MixType m where m.name = :name and m.material.materialType.id = :materialTypeId")
fun findByNameAndMaterialType(name: String, materialTypeId: Long): MixType?
/** Checks if a mix depends on the mix type with the given [id]. */
@Query(
"""
"""
select case when(count(m.id) > 0) then false else true end
from MixType t
left join Mix m on t.id = m.mixType.id
where t.id = :id
"""
from Mix m where m.mixType.id = :id
"""
)
fun canBeDeleted(id: Long): Boolean
fun isUsedByMixes(id: Long): Boolean
}

View File

@ -0,0 +1,36 @@
package dev.fyloz.colorrecipesexplorer.service
import dev.fyloz.colorrecipesexplorer.config.annotations.ServiceComponent
import dev.fyloz.colorrecipesexplorer.dtos.MixTypeDto
import dev.fyloz.colorrecipesexplorer.model.MixType
import dev.fyloz.colorrecipesexplorer.repository.MixTypeRepository
interface MixTypeService : Service<MixTypeDto, MixType, MixTypeRepository> {
/** Checks if a mix type with the given [name], [materialTypeId] and a different [id] exists. */
fun existsByNameAndMaterialType(name: String, materialTypeId: Long, id: Long? = null): Boolean
/** Finds the mix type with the given [name] and [materialTypeId]. */
fun getByNameAndMaterialType(name: String, materialTypeId: Long): MixTypeDto?
/** Checks if a mix depends on the mix type with the given [id]. */
fun isUsedByMixes(id: Long): Boolean
}
@ServiceComponent
class DefaultMixTypeService(repository: MixTypeRepository, val materialService: MaterialService) :
BaseService<MixTypeDto, MixType, MixTypeRepository>(repository), MixTypeService {
override fun existsByNameAndMaterialType(name: String, materialTypeId: Long, id: Long?) =
repository.existsByNameAndMaterialType(name, materialTypeId, id ?: 0L)
override fun getByNameAndMaterialType(name: String, materialTypeId: Long) =
repository.findByNameAndMaterialType(name, materialTypeId)?.let(::toDto)
override fun isUsedByMixes(id: Long) =
repository.isUsedByMixes(id)
override fun toDto(entity: MixType) =
MixTypeDto(entity.id!!, entity.name, materialService.toDto(entity.material))
override fun toEntity(dto: MixTypeDto) =
MixType(dto.id, dto.name, materialService.toEntity(dto.material))
}

View File

@ -0,0 +1,131 @@
package dev.fyloz.colorrecipesexplorer.logic
import dev.fyloz.colorrecipesexplorer.dtos.MaterialDto
import dev.fyloz.colorrecipesexplorer.dtos.MaterialTypeDto
import dev.fyloz.colorrecipesexplorer.dtos.MixTypeDto
import dev.fyloz.colorrecipesexplorer.exception.CannotDeleteException
import dev.fyloz.colorrecipesexplorer.service.MixTypeService
import io.mockk.*
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
import kotlin.test.assertEquals
class DefaultMixTypeLogicTest {
private val mixTypeServiceMock = mockk<MixTypeService>()
private val materialLogicMock = mockk<MaterialLogic>()
private val mixTypeLogic = spyk(DefaultMixTypeLogic(mixTypeServiceMock, materialLogicMock))
private val materialType = MaterialTypeDto(1L, "Unit test material type", "UTMT", false)
private val material = MaterialDto(1L, "Unit test material", 1000f, true, materialType)
private val mixType = MixTypeDto(id = 1L, name = "Unit test mix type", material)
@AfterEach
fun afterEach() {
clearAllMocks()
}
@Test
fun getOrCreateForNameAndMaterialType_normalBehavior_returnsFromService() {
// Arrange
every { mixTypeServiceMock.getByNameAndMaterialType(any(), any()) } returns mixType
// Act
val actualMixType = mixTypeLogic.getOrCreateForNameAndMaterialType(mixType.name, materialType)
// Assert
assertEquals(mixType, actualMixType)
}
@Test
fun getOrCreateForNameAndMaterialType_notFound_returnsFromSaveForNameAndMaterialType() {
// Arrange
every { mixTypeServiceMock.getByNameAndMaterialType(any(), any()) } returns null
every { mixTypeLogic.saveForNameAndMaterialType(any(), any()) } returns mixType
// Act
val actualMixType = mixTypeLogic.getOrCreateForNameAndMaterialType(mixType.name, materialType)
// Assert
assertEquals(mixType, actualMixType)
}
@Test
fun saveForNameAndMaterialType_normalBehavior_callsSavesInMaterialLogic() {
// Arrange
every { materialLogicMock.save(any<MaterialDto>()) } returnsArgument 0
every { mixTypeLogic.save(any()) } returnsArgument 0
// Act
mixTypeLogic.saveForNameAndMaterialType(mixType.name, materialType)
// Assert
verify {
materialLogicMock.save(match<MaterialDto> { it.name == mixType.name && it.materialType == materialType })
}
confirmVerified(materialLogicMock)
}
@Test
fun saveForNameAndMaterialType_normalBehavior_callsSave() {
// Arrange
every { materialLogicMock.save(any<MaterialDto>()) } returnsArgument 0
every { mixTypeLogic.save(any()) } returnsArgument 0
// Act
mixTypeLogic.saveForNameAndMaterialType(mixType.name, materialType)
// Assert
verify {
mixTypeLogic.save(match { it.name == mixType.name && it.material.name == mixType.name && it.material.materialType == materialType })
}
}
@Test
fun updateForNameAndMaterialType_normalBehavior_callsSavesInMaterialLogic() {
// Arrange
val updatedName = mixType.name + " updated"
val updatedMaterialType = materialType.copy(id = 2L)
every { materialLogicMock.update(any<MaterialDto>()) } returnsArgument 0
every { mixTypeLogic.update(any()) } returnsArgument 0
// Act
mixTypeLogic.updateForNameAndMaterialType(mixType, updatedName, updatedMaterialType)
// Assert
verify {
materialLogicMock.update(match<MaterialDto> { it.name == updatedName && it.materialType == updatedMaterialType })
}
confirmVerified(materialLogicMock)
}
@Test
fun updateForNameAndMaterialType_normalBehavior_callsSave() {
// Arrange
val updatedName = mixType.name + " updated"
val updatedMaterialType = materialType.copy(id = 2L)
every { materialLogicMock.update(any<MaterialDto>()) } returnsArgument 0
every { mixTypeLogic.update(any()) } returnsArgument 0
// Act
mixTypeLogic.updateForNameAndMaterialType(mixType, updatedName, updatedMaterialType)
// Assert
verify {
mixTypeLogic.update(match { it.name == updatedName && it.material.name == updatedName && it.material.materialType == updatedMaterialType })
}
}
@Test
fun deleteById_usedByMix_throwsCannotDeleteException() {
// Arrange
every { mixTypeServiceMock.isUsedByMixes(any()) } returns true
// Act
// Assert
assertThrows<CannotDeleteException> { mixTypeLogic.deleteById(mixType.id) }
}
}

View File

@ -1,172 +0,0 @@
package dev.fyloz.colorrecipesexplorer.logic
import com.nhaarman.mockitokotlin2.*
import dev.fyloz.colorrecipesexplorer.exception.AlreadyExistsException
import dev.fyloz.colorrecipesexplorer.exception.NotFoundException
import dev.fyloz.colorrecipesexplorer.model.*
import dev.fyloz.colorrecipesexplorer.repository.MixTypeRepository
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance
import org.junit.jupiter.api.assertThrows
import kotlin.test.assertEquals
import kotlin.test.assertTrue
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class MixTypeLogicTest : AbstractNamedModelServiceTest<MixType, MixTypeLogic, MixTypeRepository>() {
override val repository: MixTypeRepository = mock()
private val materialService: MaterialLogic = mock()
override val logic: MixTypeLogic = spy(DefaultMixTypeLogic(repository, materialService))
private val materialType: MaterialType = materialType()
private val material: Material = material(id = 0L, materialType = materialType)
override val entity: MixType = mixType(id = 0L, name = "mix type", material = material)
override val anotherEntity: MixType = mixType(id = 1L, name = "another mix type")
override val entityWithEntityName: MixType = mixType(id = 2L, name = entity.name)
@AfterEach
override fun afterEach() {
reset(materialService)
super.afterEach()
}
// existsByNameAndMaterialType
@Test
fun `existsByNameAndMaterialType() returns repository's answer`() {
setOf(true, false).forEach {
whenever(repository.existsByNameAndMaterialType(entity.name, materialType)).doReturn(it)
val found = logic.existsByNameAndMaterialType(entity.name, materialType)
assertTrue { found == it }
}
}
// getByMaterial()
@Test
fun `getByMaterial() returns the mix type with the given material`() {
whenever(repository.findByMaterial(material)).doReturn(entity)
val found = logic.getByMaterial(material)
assertEquals(entity, found)
}
@Test
fun `getByMaterial() throws NotFoundException when no mix type with the given material exists`() {
whenever(repository.findByMaterial(material)).doReturn(null)
assertThrows<NotFoundException> { logic.getByMaterial(material) }
.assertErrorCode("name")
}
// getByNameAndMaterialType()
@Test
fun `getByNameAndMaterialType() returns the mix type with the given name and material type`() {
whenever(repository.findByNameAndMaterialType(entity.name, materialType)).doReturn(entity)
val found = logic.getByNameAndMaterialType(entity.name, materialType)
assertEquals(entity, found)
}
// getOrCreateForNameAndMaterialType()
@Test
fun `getOrCreateForNameAndMaterialType() calls getForNameAndMaterialType() when a mix type with the given name and material type exists`() {
doReturn(true).whenever(logic).existsByNameAndMaterialType(entity.name, materialType)
doReturn(entity).whenever(logic).getByNameAndMaterialType(entity.name, materialType)
val found = logic.getOrCreateForNameAndMaterialType(entity.name, materialType)
verify(logic).getByNameAndMaterialType(entity.name, materialType)
assertEquals(entity, found)
}
@Test
fun `getOrCreateForNameAndMaterialType() calls saveForNameAndMaterialType() when no mix type with the given name and material type exists`() {
doReturn(false).whenever(logic).existsByNameAndMaterialType(entity.name, materialType)
doReturn(entity).whenever(logic).saveForNameAndMaterialType(entity.name, materialType)
val found = logic.getOrCreateForNameAndMaterialType(entity.name, materialType)
verify(logic).saveForNameAndMaterialType(entity.name, materialType)
assertEquals(entity, found)
}
// save()
@Test
fun `save() throws AlreadyExistsException when a material with the name of the new mix type exists`() {
whenever(materialService.existsByName(entity.name)).doReturn(true)
assertThrows<AlreadyExistsException> { logic.save(entity) }
.assertErrorCode("name")
}
// saveForNameAndMaterialType()
@Test
fun `saveForNameAndMaterialType() creates a save a valid mix type with the given name and material type`() {
val name = entity.name
val materialType = materialType()
doAnswer { it.arguments[0] }.whenever(logic).save(any())
val found = logic.saveForNameAndMaterialType(name, materialType)
verify(logic).save(any())
assertEquals(name, found.name)
assertEquals(name, found.material.name)
assertEquals(materialType, found.material.materialType)
assertTrue(found.material.isMixType)
}
// updateForNameAndMaterialType()
@Test
fun `updateForNameAndMaterialType() updates the given mix type with the given name and material type`() {
val mixType = mixType(id = 1L, material = material(isMixType = true))
val name = entity.name
val materialType = materialType()
doAnswer { it.arguments[0] }.whenever(logic).update(any())
val found = logic.updateForNameAndMaterialType(mixType, name, materialType)
verify(logic).update(any())
assertEquals(mixType.id, found.id)
assertEquals(name, found.name)
assertEquals(name, found.material.name)
assertEquals(materialType, found.material.materialType)
assertTrue(found.material.isMixType)
}
// delete()
override fun `delete() deletes in the repository`() {
whenCanBeDeleted {
super.`delete() deletes in the repository`()
}
}
// deleteById()
override fun `deleteById() deletes the entity with the given id in the repository`() {
whenCanBeDeleted {
super.`deleteById() deletes the entity with the given id in the repository`()
}
}
private fun whenCanBeDeleted(id: Long = any(), test: () -> Unit) {
whenever(repository.canBeDeleted(id)).doReturn(true)
test()
}
}