La création d'un mélange vérifie si le type de mélange existe avant de tenter de le créer.

This commit is contained in:
FyloZ 2021-03-09 19:51:31 -05:00
parent 16f4a36693
commit 81c9f82a9f
5 changed files with 95 additions and 13 deletions

View File

@ -1,15 +1,23 @@
package dev.fyloz.trial.colorrecipesexplorer.repository
import dev.fyloz.trial.colorrecipesexplorer.model.Material
import dev.fyloz.trial.colorrecipesexplorer.model.MaterialType
import dev.fyloz.trial.colorrecipesexplorer.model.MixType
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
/** 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?
@Query(
"""
select case when(count(m.id) > 0) then false else true end

View File

@ -34,7 +34,7 @@ class MixServiceImpl(
override fun save(entity: MixSaveDto): Mix {
val recipe = recipeService.getById(entity.recipeId)
val materialType = materialTypeService.getById(entity.materialTypeId)
val mixType = mixTypeService.createForNameAndMaterialType(entity.name, materialType)
val mixType = mixTypeService.getOrCreateForNameAndMaterialType(entity.name, materialType)
var mix = save(mix(recipe = recipe, mixType = mixType))
val mixMaterials =
@ -84,7 +84,7 @@ class MixServiceImpl(
val mix = getById(entity.id)
if (entity.name != null || entity.materialTypeId != null) {
mix.mixType = if (mixTypeIsShared(mix.mixType)) {
mixTypeService.createForNameAndMaterialType(
mixTypeService.saveForNameAndMaterialType(
entity.name ?: mix.mixType.name,
if (entity.materialTypeId != null) materialTypeService.getById(entity.materialTypeId) else mix.mixType.material.materialType!!
)

View File

@ -9,11 +9,20 @@ import org.springframework.context.annotation.Lazy
import org.springframework.stereotype.Service
interface MixTypeService : 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
/** Returns a new and persisted [MixType] with the given [name] and [materialType]. */
fun createForNameAndMaterialType(name: String, materialType: MaterialType): MixType
fun saveForNameAndMaterialType(name: String, materialType: MaterialType): MixType
/** Returns the given [mixType] updated with the given [name] and [materialType]. */
fun updateForNameAndMaterialType(mixType: MixType, name: String, materialType: MaterialType): MixType
@ -26,16 +35,29 @@ class MixTypeServiceImpl(
@Lazy val mixService: MixService
) :
AbstractNamedModelService<MixType, MixTypeRepository>(mixTypeRepository), MixTypeService {
override fun existsByNameAndMaterialType(name: String, materialType: MaterialType): Boolean =
repository.existsByNameAndMaterialType(name, materialType)
override fun getByMaterial(material: Material): MixType =
repository.findByMaterial(material) ?: throw EntityNotFoundRestException(material.name)
override fun getByNameAndMaterialType(name: String, materialType: MaterialType): MixType =
repository.findByNameAndMaterialType(name, materialType)
?: throw EntityNotFoundRestException("$name/${materialType.name}")
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 (materialService.existsByName(entity.name))
throw EntityAlreadyExistsRestException(entity.name)
return super.save(entity)
}
override fun createForNameAndMaterialType(name: String, materialType: MaterialType): MixType =
override fun saveForNameAndMaterialType(name: String, materialType: MaterialType): MixType =
save(
mixType(
name = name,

View File

@ -36,6 +36,7 @@ class MixServiceTest : AbstractExternalModelServiceTest<Mix, MixSaveDto, MixUpda
// save()
@Test
override fun `save(dto) calls and returns save() with the created entity`() {
val recipe = recipe(id = entitySaveDto.recipeId)
val materialType = materialType(id = entitySaveDto.materialTypeId)
@ -54,7 +55,7 @@ class MixServiceTest : AbstractExternalModelServiceTest<Mix, MixSaveDto, MixUpda
whenever(recipeService.getById(recipe.id!!)).doReturn(recipe)
whenever(materialTypeService.getById(materialType.id!!)).doReturn(materialType)
whenever(mixMaterialService.createFromMap(mixWithId, entitySaveDto.mixMaterials!!)).doReturn(mixMaterials)
whenever(mixTypeService.createForNameAndMaterialType(mixType.name, mixType.material.materialType!!)).doReturn(
whenever(mixTypeService.getOrCreateForNameAndMaterialType(mixType.name, mixType.material.materialType!!)).doReturn(
mixType
)
doReturn(true).whenever(service).existsById(mixWithId.id!!)
@ -68,7 +69,7 @@ class MixServiceTest : AbstractExternalModelServiceTest<Mix, MixSaveDto, MixUpda
verify(recipeService).addMix(recipe, mix)
// Verify if this method is called instead of the MixType's constructor, which does not check if the name is already taken by a material.
verify(mixTypeService).createForNameAndMaterialType(mixType.name, mixType.material.materialType!!)
verify(mixTypeService).getOrCreateForNameAndMaterialType(mixType.name, mixType.material.materialType!!)
assertEquals(mixWithMaterials, found)
}
@ -115,14 +116,14 @@ class MixServiceTest : AbstractExternalModelServiceTest<Mix, MixSaveDto, MixUpda
}
@Test
fun `update(dto) calls MixTypeService createForNameAndMaterialType() when mix type is shared`() {
fun `update(dto) calls MixTypeService saveForNameAndMaterialType() when mix type is shared`() {
mixUpdateDtoMixTypeTest(sharedMixType = true) {
whenever(mixTypeService.createForNameAndMaterialType(mixUpdateDto.name!!, materialType))
whenever(mixTypeService.saveForNameAndMaterialType(mixUpdateDto.name!!, materialType))
.doReturn(newMixType)
val found = service.update(mixUpdateDto)
verify(mixTypeService).createForNameAndMaterialType(mixUpdateDto.name!!, materialType)
verify(mixTypeService).saveForNameAndMaterialType(mixUpdateDto.name!!, materialType)
assertEquals(newMixType, found.mixType)
}

View File

@ -9,6 +9,7 @@ import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertTrue
class MixTypeServiceTest : AbstractNamedModelServiceTest<MixType, MixTypeService, MixTypeRepository>() {
@ -17,7 +18,8 @@ class MixTypeServiceTest : AbstractNamedModelServiceTest<MixType, MixTypeService
private val mixService: MixService = mock()
override val service: MixTypeService = spy(MixTypeServiceImpl(repository, materialService, mixService))
private val material: Material = material(id = 0L)
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)
@ -28,6 +30,19 @@ class MixTypeServiceTest : AbstractNamedModelServiceTest<MixType, MixTypeService
super.afterEach()
}
// existsByNameAndMaterialType
@Test
fun `existsByNameAndMaterialType() returns repository's answer`() {
setOf(true, false).forEach {
whenever(repository.existsByNameAndMaterialType(entity.name, materialType)).doReturn(it)
val found = service.existsByNameAndMaterialType(entity.name, materialType)
assertTrue { found == it }
}
}
// getByMaterial()
@Test
@ -47,6 +62,42 @@ class MixTypeServiceTest : AbstractNamedModelServiceTest<MixType, MixTypeService
assertEquals(material.name, exception.value)
}
// 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 = service.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(service).existsByNameAndMaterialType(entity.name, materialType)
doReturn(entity).whenever(service).getByNameAndMaterialType(entity.name, materialType)
val found = service.getOrCreateForNameAndMaterialType(entity.name, materialType)
verify(service).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(service).existsByNameAndMaterialType(entity.name, materialType)
doReturn(entity).whenever(service).saveForNameAndMaterialType(entity.name, materialType)
val found = service.getOrCreateForNameAndMaterialType(entity.name, materialType)
verify(service).saveForNameAndMaterialType(entity.name, materialType)
assertEquals(entity, found)
}
// save()
@Test
@ -57,16 +108,16 @@ class MixTypeServiceTest : AbstractNamedModelServiceTest<MixType, MixTypeService
assertEquals(entity.name, exception.value)
}
// createForNameAndMaterialType()
// saveForNameAndMaterialType()
@Test
fun `createForNameAndMaterialType() creates a save a valid mix type with the given name and material type`() {
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(service).save(any())
val found = service.createForNameAndMaterialType(name, materialType)
val found = service.saveForNameAndMaterialType(name, materialType)
verify(service).save(any())