Ajout des tests des configurations

This commit is contained in:
FyloZ 2021-05-28 18:18:01 -04:00
parent f376d66b2e
commit feabcc5b76
10 changed files with 289 additions and 30 deletions

View File

@ -48,7 +48,7 @@ package:
ARTIFACT_NAME: "ColorRecipesExplorer-backend-$CI_PIPELINE_IID"
script:
- docker rm $PACKAGE_CONTAINER_NAME || true
- docker run --name $PACKAGE_CONTAINER_NAME $CI_REGISTRY_IMAGE_GRADLE gradle bootJar
- docker run --name $PACKAGE_CONTAINER_NAME $CI_REGISTRY_IMAGE_GRADLE gradle bootJar -Pversion=$CI_PIPELINE_IID
- docker cp $PACKAGE_CONTAINER_NAME:/usr/src/cre/build/libs/ColorRecipesExplorer.jar $ARTIFACT_NAME.jar
- docker build -t $CI_REGISTRY_IMAGE_BACKEND --build-arg JDK_VERSION=$JDK_VERSION --build-arg PORT=$PORT --build-arg ARTIFACT_NAME=$ARTIFACT_NAME .
- docker push $CI_REGISTRY_IMAGE_BACKEND
@ -81,4 +81,4 @@ deploy:
script:
- ssh -p $DEPLOYMENT_SERVER_SSH_PORT $DEPLOYMENT_SERVER_USERNAME@$DEPLOYMENT_SERVER "docker stop $DEPLOYED_CONTAINER_NAME || true && docker rm $DEPLOYED_CONTAINER_NAME || true"
- ssh -p $DEPLOYMENT_SERVER_SSH_PORT $DEPLOYMENT_SERVER_USERNAME@$DEPLOYMENT_SERVER "docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY && docker pull $CI_REGISTRY_IMAGE_BACKEND"
- ssh -p $DEPLOYMENT_SERVER_SSH_PORT $DEPLOYMENT_SERVER_USERNAME@$DEPLOYMENT_SERVER "docker run -d -p $PORT:$PORT --name=$DEPLOYED_CONTAINER_NAME -v $DATA_VOLUME:/usr/bin/cre/data -e spring_profiles_active=$SPRING_PROFILES -e spring_datasource_username=$DB_USERNAME -e spring_datasource_password=$DB_PASSWORD -e spring_datasource_url=$DB_URL -e databaseupdater_username=$DB_UPDATE_USERNAME -e databaseupdater_password=$DB_UPDATE_PASSWORD $CI_REGISTRY_IMAGE_BACKEND"
- ssh -p $DEPLOYMENT_SERVER_SSH_PORT $DEPLOYMENT_SERVER_USERNAME@$DEPLOYMENT_SERVER "docker run -d -p $PORT:$PORT --name=$DEPLOYED_CONTAINER_NAME -v $DATA_VOLUME:/usr/bin/cre/data -e spring_profiles_active=$SPRING_PROFILES -e $CI_REGISTRY_IMAGE_BACKEND"

View File

@ -62,6 +62,10 @@ dependencies {
implementation("org.springframework.cloud:spring-cloud-starter:2.2.8.RELEASE")
}
springBoot {
buildInfo()
}
java {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11

View File

@ -1 +0,0 @@
-1

View File

@ -14,6 +14,7 @@ import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.DependsOn
import org.springframework.context.annotation.Profile
import org.springframework.core.env.ConfigurableEnvironment
import java.lang.RuntimeException
import javax.sql.DataSource
const val SUPPORTED_DATABASE_VERSION = 5
@ -44,7 +45,7 @@ class DataSourceConfiguration {
username = databaseUsername
password = databasePassword
})
} catch (ex: CreDatabaseException) {
} catch (ex: Exception) {
logger.error("Could not access database, restarting in emergency mode...", ex)
emergencyMode = true

View File

@ -39,6 +39,9 @@ data class ConfigurationEntity(
) {
fun toConfiguration() =
configuration(key.toConfigurationType(), content, lastUpdated)
override fun equals(other: Any?) =
other is ConfigurationEntity && key == other.key && content == other.content
}
data class ConfigurationDto(

View File

@ -8,6 +8,7 @@ import dev.fyloz.colorrecipesexplorer.emergencyMode
import dev.fyloz.colorrecipesexplorer.model.*
import dev.fyloz.colorrecipesexplorer.repository.ConfigurationRepository
import dev.fyloz.colorrecipesexplorer.service.files.FileService
import org.springframework.boot.info.BuildProperties
import org.springframework.context.annotation.Lazy
import org.springframework.data.repository.findByIdOrNull
import org.springframework.stereotype.Service
@ -51,6 +52,7 @@ interface ConfigurationService {
const val CONFIGURATION_LOGO_FILE_PATH = "images/logo"
const val CONFIGURATION_ICON_FILE_PATH = "images/icon"
const val CONFIGURATION_FORMATTED_LIST_DELIMITER = ';'
@Service
class ConfigurationServiceImpl(
@ -58,7 +60,8 @@ class ConfigurationServiceImpl(
private val fileService: FileService,
private val fileConfiguration: FileConfiguration,
private val creProperties: CreProperties,
private val databaseProperties: DatabaseUpdaterProperties
private val databaseProperties: DatabaseUpdaterProperties,
private val buildInfo: BuildProperties
) : ConfigurationService {
override fun getAll() =
ConfigurationType.values().mapNotNull {
@ -70,7 +73,7 @@ class ConfigurationServiceImpl(
}
override fun getAll(formattedKeyList: String) =
formattedKeyList.split(';').map(this::get)
formattedKeyList.split(CONFIGURATION_FORMATTED_LIST_DELIMITER).map(this::get)
override fun get(key: String) =
get(key.toConfigurationType())
@ -131,25 +134,19 @@ class ConfigurationServiceImpl(
ConfigurationType.TOUCH_UP_KIT_CACHE_PDF -> "true"
else -> ""
}
}
private fun getComputedConfiguration(key: ConfigurationType) = configuration(
key, when (key) {
ConfigurationType.EMERGENCY_MODE_ENABLED -> emergencyMode
ConfigurationType.VERSION -> getAppVersion()
ConfigurationType.DATABASE_SUPPORTED_VERSION -> SUPPORTED_DATABASE_VERSION
ConfigurationType.JAVA_VERSION -> Runtime.version()
ConfigurationType.OPERATING_SYSTEM -> "${System.getProperty("os.name")} ${System.getProperty("os.version")} ${
System.getProperty(
"os.arch"
)
}"
else -> throw IllegalArgumentException("Cannot get the value of the configuration with the key ${key.key} because it is not a computed configuration")
}.toString()
)
const val APP_VERSION_PATH = "buildversion"
fun getAppVersion(): Int = with(File(APP_VERSION_PATH)) {
this.readLines()[0].toInt()
private fun getComputedConfiguration(key: ConfigurationType) = configuration(
key, when (key) {
ConfigurationType.EMERGENCY_MODE_ENABLED -> emergencyMode
ConfigurationType.VERSION -> buildInfo.version
ConfigurationType.DATABASE_SUPPORTED_VERSION -> SUPPORTED_DATABASE_VERSION
ConfigurationType.JAVA_VERSION -> Runtime.version()
ConfigurationType.OPERATING_SYSTEM -> "${System.getProperty("os.name")} ${System.getProperty("os.version")} ${
System.getProperty(
"os.arch"
)
}"
else -> throw IllegalArgumentException("Cannot get the value of the configuration with the key ${key.key} because it is not a computed configuration")
}.toString()
)
}

View File

@ -0,0 +1,255 @@
package dev.fyloz.colorrecipesexplorer.service
import dev.fyloz.colorrecipesexplorer.config.FileConfiguration
import dev.fyloz.colorrecipesexplorer.model.*
import dev.fyloz.colorrecipesexplorer.repository.ConfigurationRepository
import io.mockk.*
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
import java.time.LocalDateTime
import java.util.*
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertTrue
class ConfigurationServiceTest {
private val repository = mockk<ConfigurationRepository>()
private val fileConfiguration = mockk<FileConfiguration>()
private val service = spyk(ConfigurationServiceImpl(repository, mockk(), fileConfiguration, mockk(), mockk(), mockk()))
@AfterEach
fun afterEach() {
clearAllMocks()
}
// getAll()
@Test
fun `getAll() gets the Configuration of each ConfigurationType`() {
every { service.get(any<ConfigurationType>()) } answers { throw ConfigurationNotSetException(this.args[0] as ConfigurationType) }
service.getAll()
verify {
service.getAll()
ConfigurationType.values().forEach {
service.get(it)
}
}
confirmVerified(service)
}
@Test
fun `getAll() only returns set configurations`() {
val unsetConfigurationTypes = listOf(
ConfigurationType.INSTANCE_NAME,
ConfigurationType.INSTANCE_LOGO_PATH,
ConfigurationType.INSTANCE_ICON_PATH
)
every { service.get(match<ConfigurationType> { it in unsetConfigurationTypes }) } answers {
throw ConfigurationNotSetException(this.firstArg() as ConfigurationType)
}
every { service.get(match<ConfigurationType> { it !in unsetConfigurationTypes }) } answers {
val type = firstArg<ConfigurationType>()
configuration(type, type.key)
}
val found = service.getAll()
assertFalse {
found.any {
it.type in unsetConfigurationTypes
}
}
verify {
service.getAll()
ConfigurationType.values().forEach {
service.get(it)
}
}
confirmVerified(service)
}
@Test
fun `getAll() only includes configurations matching the formatted formatted key list`() {
val configurationTypes = listOf(
ConfigurationType.INSTANCE_NAME,
ConfigurationType.INSTANCE_LOGO_PATH,
ConfigurationType.INSTANCE_ICON_PATH
)
val formattedKeyList = configurationTypes
.map { it.key }
.reduce { acc, s -> "$acc$CONFIGURATION_FORMATTED_LIST_DELIMITER$s" }
every { service.get(any<String>()) } answers {
val key = firstArg<String>()
configuration(key.toConfigurationType(), key)
}
val found = service.getAll(formattedKeyList)
assertTrue {
found.all { it.type in configurationTypes }
}
verify {
service.getAll(formattedKeyList)
configurationTypes.forEach {
service.get(it.key)
}
}
confirmVerified(service)
}
// get()
@Test
fun `get(key) calls get() with the ConfigurationType matching the given key`() {
val type = ConfigurationType.INSTANCE_ICON_PATH
val key = type.key
every { service.get(type) } answers {
val type = firstArg<ConfigurationType>()
configuration(type, type.key)
}
service.get(key)
verify {
service.get(key)
service.get(type)
}
confirmVerified(service)
}
@Test
fun `get(type) gets in the repository when the given ConfigurationType is not computed or a file property`() {
val type = ConfigurationType.INSTANCE_ICON_PATH
every { repository.findById(type.key) } returns Optional.of(
ConfigurationEntity(type.key, type.key, LocalDateTime.now())
)
val configuration = service.get(type)
assertTrue {
configuration.key == type.key
}
verify {
service.get(type)
repository.findById(type.key)
}
confirmVerified(service, repository)
}
@Test
fun `get(type) gets in the FileConfiguration when the gien ConfigurationType is a file property`() {
val type = ConfigurationType.DATABASE_URL
every { fileConfiguration.get(type) } returns configuration(type, type.key)
val configuration = service.get(type)
assertTrue {
configuration.key == type.key
}
verify {
service.get(type)
fileConfiguration.get(type)
}
verify(exactly = 0) {
repository.findById(type.key)
}
confirmVerified(service, fileConfiguration, repository)
}
@Test
fun `get(type) computes computed properties`() {
val type = ConfigurationType.JAVA_VERSION
val configuration = service.get(type)
assertTrue {
configuration.key == type.key
}
verify {
service.get(type)
}
verify(exactly = 0) {
repository.findById(type.key)
fileConfiguration.get(type)
}
confirmVerified(service, repository, fileConfiguration)
}
@Test
fun `get(type) throws ConfigurationNotSetException when the given ConfigurationType has no set configuration`() {
val type = ConfigurationType.INSTANCE_ICON_PATH
every { repository.findById(type.key) } returns Optional.empty()
with(assertThrows<ConfigurationNotSetException> { service.get(type) }) {
assertEquals(type, this.type)
}
verify {
service.get(type)
repository.findById(type.key)
}
}
@Test
fun `set() set the configuration in the FileConfiguration when the given ConfigurationType is a file configuration`() {
val type = ConfigurationType.DATABASE_URL
val content = "url"
every { fileConfiguration.set(type, content) } just runs
service.set(type, content)
verify {
service.set(type, content)
fileConfiguration.set(type, content)
}
confirmVerified(service, fileConfiguration)
}
@Test
fun `set() set the configuration in the repository when the given ConfigurationType is not a computed configuration of a file configuration`() {
val type = ConfigurationType.INSTANCE_ICON_PATH
val content = "path"
val configuration = configuration(type, content)
val entity = configuration.toEntity()
every { repository.save(entity) } returns entity
service.set(type, content)
verify {
service.set(type, content)
repository.save(entity)
}
confirmVerified(service, repository)
}
@Test
fun `set() throws CannotSetComputedConfigurationException when the given ConfigurationType is a computed configuration`() {
val type = ConfigurationType.JAVA_VERSION
val content = "5"
with(assertThrows<CannotSetComputedConfigurationException> { service.set(type, content) }) {
assertEquals(type, this.type)
}
verify {
service.set(type, content)
}
confirmVerified(service)
}
}

View File

@ -23,7 +23,7 @@ class MaterialServiceTest :
private val materialTypeService: MaterialTypeService = mock()
private val fileService: FileService = mock()
override val service: MaterialService =
spy(MaterialServiceImpl(repository, recipeService, mixService, materialTypeService, fileService))
spy(MaterialServiceImpl(repository, recipeService, mixService, materialTypeService, fileService, mock()))
override val entity: Material = material(id = 0L, name = "material")
private val entityOutput = materialOutputDto(entity)

View File

@ -27,7 +27,7 @@ class RecipeServiceTest :
private val groupService: GroupService = mock()
private val recipeStepService: RecipeStepService = mock()
override val service: RecipeService =
spy(RecipeServiceImpl(repository, companyService, mixService, recipeStepService, groupService, mock()))
spy(RecipeServiceImpl(repository, companyService, mixService, recipeStepService, groupService, mock(), mock()))
private val company: Company = company(id = 0L)
override val entity: Recipe = recipe(id = 0L, name = "recipe", company = company)

View File

@ -21,7 +21,7 @@ private class TouchUpKitServiceTestContext {
val creProperties = mockk<CreProperties> {
every { cacheGeneratedFiles } returns false
}
val touchUpKitService = spyk(TouchUpKitServiceImpl(fileService, touchUpKitRepository, creProperties))
val touchUpKitService = spyk(TouchUpKitServiceImpl(fileService, mockk(), touchUpKitRepository))
val pdfDocumentData = mockk<ByteArrayResource>()
val pdfDocument = mockk<PdfDocument> {
mockkStatic(PdfDocument::toByteArrayResource)