From 997bfbf97c009d6e82b6d5520a1b51eeedfcba87 Mon Sep 17 00:00:00 2001 From: Elena Moshnikova <15213856+ElenaSpb@users.noreply.github.com> Date: Sun, 17 Nov 2024 15:48:58 +0300 Subject: [PATCH] 2369 add caching (#2645) * 2369 some optimization and adding caching --- build.gradle.kts | 2 + .../com/epam/brn/config/CachingConfig.kt | 8 ++ .../com/epam/brn/model/ExerciseGroup.kt | 10 +- .../epam/brn/service/ExerciseGroupsService.kt | 28 ++---- .../com/epam/brn/service/SeriesService.kt | 8 +- .../com/epam/brn/service/SubGroupService.kt | 24 +++-- .../com/epam/brn/service/TaskService.kt | 13 +-- .../epam/brn/service/UrlConversionService.kt | 8 +- .../kotlin/com/epam/brn/integration/BaseIT.kt | 27 +++--- .../brn/integration/ExercisesControllerIT.kt | 29 ++---- .../epam/brn/integration/GroupControllerIT.kt | 94 ++++++++++++++----- .../brn/integration/SeriesControllerIT.kt | 18 ++-- .../brn/integration/SubGroupControllerIT.kt | 13 ++- .../epam/brn/integration/TaskControllerIT.kt | 15 +-- .../brn/service/ExerciseGroupServiceTest.kt | 31 +++--- 15 files changed, 183 insertions(+), 145 deletions(-) create mode 100644 src/main/kotlin/com/epam/brn/config/CachingConfig.kt diff --git a/build.gradle.kts b/build.gradle.kts index c83a64b4c..8695e5103 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -52,8 +52,10 @@ dependencies { implementation("org.springframework.boot:spring-boot-starter-batch") implementation("org.springframework.boot:spring-boot-starter-security") implementation("org.springframework.boot:spring-boot-starter-validation") + implementation("org.springframework.boot:spring-boot-starter-cache") implementation("org.springframework.security:spring-security-test") implementation("org.springframework.boot:spring-boot-devtools") + implementation("org.postgresql:postgresql") implementation("org.flywaydb:flyway-core:$flywayVersion") diff --git a/src/main/kotlin/com/epam/brn/config/CachingConfig.kt b/src/main/kotlin/com/epam/brn/config/CachingConfig.kt new file mode 100644 index 000000000..876e275b9 --- /dev/null +++ b/src/main/kotlin/com/epam/brn/config/CachingConfig.kt @@ -0,0 +1,8 @@ +package com.epam.brn.config + +import org.springframework.cache.annotation.EnableCaching +import org.springframework.context.annotation.Configuration + +@Configuration +@EnableCaching +class CachingConfig diff --git a/src/main/kotlin/com/epam/brn/model/ExerciseGroup.kt b/src/main/kotlin/com/epam/brn/model/ExerciseGroup.kt index a55387ecb..ff4e8a9ea 100644 --- a/src/main/kotlin/com/epam/brn/model/ExerciseGroup.kt +++ b/src/main/kotlin/com/epam/brn/model/ExerciseGroup.kt @@ -6,6 +6,7 @@ import com.epam.brn.upload.csv.group.GroupRecord import javax.persistence.CascadeType import javax.persistence.Column import javax.persistence.Entity +import javax.persistence.FetchType import javax.persistence.GeneratedValue import javax.persistence.GenerationType import javax.persistence.Id @@ -27,7 +28,7 @@ data class ExerciseGroup( val name: String, @Column val description: String? = "", - @OneToMany(mappedBy = "exerciseGroup", cascade = [(CascadeType.ALL)]) + @OneToMany(mappedBy = "exerciseGroup", fetch = FetchType.LAZY, cascade = [(CascadeType.ALL)]) val series: MutableList = ArrayList() ) { constructor(record: GroupRecord) : this( @@ -45,6 +46,13 @@ data class ExerciseGroup( series = series.map { series -> series.id }.toMutableList() ) + fun toDtoWithoutSeries() = ExerciseGroupDto( + id = id, + locale = locale, + name = name, + description = description + ) + override fun equals(other: Any?): Boolean { if (this === other) return true if (javaClass != other?.javaClass) return false diff --git a/src/main/kotlin/com/epam/brn/service/ExerciseGroupsService.kt b/src/main/kotlin/com/epam/brn/service/ExerciseGroupsService.kt index fc448c5da..a46efca07 100644 --- a/src/main/kotlin/com/epam/brn/service/ExerciseGroupsService.kt +++ b/src/main/kotlin/com/epam/brn/service/ExerciseGroupsService.kt @@ -6,6 +6,7 @@ import com.epam.brn.model.ExerciseGroup import com.epam.brn.repo.ExerciseGroupRepository import org.apache.logging.log4j.kotlin.logger import org.springframework.beans.factory.annotation.Autowired +import org.springframework.cache.annotation.Cacheable import org.springframework.stereotype.Service import java.util.Optional @@ -15,34 +16,25 @@ class ExerciseGroupsService( ) { private val log = logger() - fun findAllGroups(): List { - log.debug("Searching all groups") - val groups: List = exerciseGroupRepository.findAll() - return groups.map { group -> group.toDto() } - } - + @Cacheable("groupsById") fun findGroupDtoById(groupId: Long): ExerciseGroupDto { log.debug("Searching group with id=$groupId") val group: Optional = exerciseGroupRepository.findById(groupId) - return group.map { x -> x.toDto() } - .orElseThrow { EntityNotFoundException("no group was found for id=$groupId") } + return group.map { it.toDto() } + .orElseThrow { EntityNotFoundException("No group was found for id=$groupId") } } + @Cacheable("groupsByLocale") fun findByLocale(locale: String): List { - log.debug("Searching groups by locale=$locale") - if (locale.isEmpty()) - return exerciseGroupRepository.findAll().map { group -> group.toDto() } - return exerciseGroupRepository.findByLocale(locale) - .map { group -> group.toDto() } - } - - fun save(exerciseGroup: ExerciseGroup): ExerciseGroup { - return exerciseGroupRepository.save(exerciseGroup) + return if (locale.isEmpty()) + exerciseGroupRepository.findAll().map { group -> group.toDtoWithoutSeries() } + else exerciseGroupRepository.findByLocale(locale) + .map { group -> group.toDtoWithoutSeries() } } fun findGroupByCode(groupCode: String): ExerciseGroup { log.debug("Searching group with code=$groupCode") return exerciseGroupRepository.findByCode(groupCode) - .orElseThrow { EntityNotFoundException("no group was found for code=$groupCode") } + .orElseThrow { EntityNotFoundException("No group was found for code=$groupCode") } } } diff --git a/src/main/kotlin/com/epam/brn/service/SeriesService.kt b/src/main/kotlin/com/epam/brn/service/SeriesService.kt index a2bb86fff..f1e3fac5a 100644 --- a/src/main/kotlin/com/epam/brn/service/SeriesService.kt +++ b/src/main/kotlin/com/epam/brn/service/SeriesService.kt @@ -2,9 +2,9 @@ package com.epam.brn.service import com.epam.brn.dto.SeriesDto import com.epam.brn.exception.EntityNotFoundException -import com.epam.brn.model.Series import com.epam.brn.repo.SeriesRepository import org.apache.logging.log4j.kotlin.logger +import org.springframework.cache.annotation.Cacheable import org.springframework.stereotype.Service @Service @@ -12,20 +12,18 @@ class SeriesService(private val seriesRepository: SeriesRepository) { private val log = logger() + @Cacheable("series") fun findSeriesForGroup(groupId: Long): List { log.debug("try to find series for groupId=$groupId") val series = seriesRepository.findByExerciseGroupLike(groupId) return series.map { seriesEntry -> seriesEntry.toDto() } } + @Cacheable("seriesDto") fun findSeriesDtoForId(seriesId: Long): SeriesDto { log.debug("try to find series for seriesId=$seriesId") val series = seriesRepository.findById(seriesId) .orElseThrow { EntityNotFoundException("no series was found for id=$seriesId") } return series.toDto() } - - fun save(series: Series): Series { - return seriesRepository.save(series) - } } diff --git a/src/main/kotlin/com/epam/brn/service/SubGroupService.kt b/src/main/kotlin/com/epam/brn/service/SubGroupService.kt index ece38c15a..d55c57214 100644 --- a/src/main/kotlin/com/epam/brn/service/SubGroupService.kt +++ b/src/main/kotlin/com/epam/brn/service/SubGroupService.kt @@ -9,8 +9,10 @@ import com.epam.brn.repo.ExerciseRepository import com.epam.brn.repo.SeriesRepository import com.epam.brn.repo.SubGroupRepository import org.apache.logging.log4j.kotlin.logger +import org.springframework.cache.annotation.CacheEvict +import org.springframework.cache.annotation.CachePut +import org.springframework.cache.annotation.Cacheable import org.springframework.stereotype.Service -import java.util.stream.Collectors @Service class SubGroupService( @@ -21,25 +23,23 @@ class SubGroupService( ) { private val log = logger() + @Cacheable("subgroupsBySeriesId") fun findSubGroupsForSeries(seriesId: Long): List { - log.debug("Try to find subGroups for seriesId=$seriesId") return subGroupRepository .findBySeriesId(seriesId) - .parallelStream() .map { subGroup -> toSubGroupResponse(subGroup) } - .collect(Collectors.toList()) .sortedWith(compareBy({ it.level }, { it.withPictures })) } + @Cacheable("subgroupsBySubGroupId") fun findById(subGroupId: Long): SubGroupResponse { - log.debug("try to find SubGroup by Id=$subGroupId") val subGroup = subGroupRepository.findById(subGroupId) .orElseThrow { EntityNotFoundException("No subGroup was found by id=$subGroupId.") } return toSubGroupResponse(subGroup) } + @CacheEvict("subgroupsBySeriesId", "subgroupsBySubGroupId") fun deleteSubGroupById(subGroupId: Long) { - log.debug("try to delete SubGroup by Id=$subGroupId") if (subGroupRepository.existsById(subGroupId)) { if (exerciseRepository.existsBySubGroupId(subGroupId)) throw IllegalArgumentException("Can not delete subGroup because there are exercises that refer to the subGroup.") @@ -48,8 +48,8 @@ class SubGroupService( throw IllegalArgumentException("Can not delete subGroup because subGroup is not found by this id.") } + @CachePut("subgroupsBySeriesId", "subgroupsBySubGroupId") fun updateSubGroupById(subGroupId: Long, subGroupChangeRequest: SubGroupChangeRequest): SubGroupResponse { - log.debug("try to update SubGroup by Id=$subGroupId") val subGroup = subGroupRepository.findById(subGroupId) .orElseThrow { EntityNotFoundException("Can not update subGroup because subGroup is not found by this id.") } subGroup.withPictures = subGroupChangeRequest.withPictures @@ -59,15 +59,13 @@ class SubGroupService( fun addSubGroupToSeries(subGroupRequest: SubGroupRequest, seriesId: Long): SubGroupResponse { log.debug("try to find subgroup by name=${subGroupRequest.name} and the level=${subGroupRequest.level}") - val existSubGroup = subGroupRepository.findByNameAndLevel(subGroupRequest.name, subGroupRequest.level!!) + val level = subGroupRequest.level ?: throw IllegalArgumentException("Level is required") + val existSubGroup = subGroupRepository.findByNameAndLevel(subGroupRequest.name, level) if (existSubGroup != null) - throw IllegalArgumentException("The subgroup with name=${subGroupRequest.name} and the level=${subGroupRequest.level} already exists!") - log.debug("try to find Series by Id=$seriesId") + throw IllegalArgumentException("The subgroup with name=${subGroupRequest.name} and the level=$level already exists!") val series = seriesRepository.findById(seriesId) .orElseThrow { EntityNotFoundException("No series was found by id=$seriesId.") } - val subGroup = subGroupRequest.toModel(series) - val savedSubGroup = subGroupRepository.save(subGroup) - return toSubGroupResponse(savedSubGroup) + return toSubGroupResponse(subGroupRepository.save(subGroupRequest.toModel(series))) } fun toSubGroupResponse(subGroup: SubGroup): SubGroupResponse { diff --git a/src/main/kotlin/com/epam/brn/service/TaskService.kt b/src/main/kotlin/com/epam/brn/service/TaskService.kt index afdb4a064..61dde3792 100644 --- a/src/main/kotlin/com/epam/brn/service/TaskService.kt +++ b/src/main/kotlin/com/epam/brn/service/TaskService.kt @@ -21,6 +21,8 @@ import com.epam.brn.repo.ResourceRepository import com.epam.brn.repo.TaskRepository import com.epam.brn.service.cloud.CloudService import org.apache.logging.log4j.kotlin.logger +import org.springframework.cache.annotation.CacheEvict +import org.springframework.cache.annotation.Cacheable import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @@ -33,6 +35,7 @@ class TaskService( ) { private val log = logger() + @Cacheable("tasksByExerciseId") fun getTasksByExerciseId(exerciseId: Long): List { val exercise: Exercise = exerciseRepository.findById(exerciseId) .orElseThrow { EntityNotFoundException("No exercise found for id=$exerciseId") } @@ -51,6 +54,7 @@ class TaskService( } } + @Cacheable("tasksById") fun getTaskById(taskId: Long): Any { log.debug("Searching task with id=$taskId") val task = @@ -75,6 +79,7 @@ class TaskService( } } + @CacheEvict("tasksByExerciseId", "tasksById") @Transactional fun save(task: Task): Task { val resources = mutableSetOf() @@ -85,13 +90,9 @@ class TaskService( } } -val vowels = "а,е,ё,и,о,у,э,ы,ю,я".toCharArray() +private val vowelSet = setOf('а', 'е', 'ё', 'и', 'о', 'у', 'э', 'ы', 'ю', 'я') -fun String.findSyllableCount(): Int { - var syllableCount = 0 - this.toCharArray().forEach { if (vowels.contains(it)) syllableCount++ } - return syllableCount -} +fun String.findSyllableCount(): Int = count { it in vowelSet } fun Task.toDetailWordsTaskDto(exerciseType: ExerciseType) = TaskResponse( id = id!!, diff --git a/src/main/kotlin/com/epam/brn/service/UrlConversionService.kt b/src/main/kotlin/com/epam/brn/service/UrlConversionService.kt index c78a5e8ea..19fd13aac 100644 --- a/src/main/kotlin/com/epam/brn/service/UrlConversionService.kt +++ b/src/main/kotlin/com/epam/brn/service/UrlConversionService.kt @@ -1,7 +1,6 @@ package com.epam.brn.service import com.epam.brn.service.cloud.CloudService -import org.apache.logging.log4j.kotlin.logger import org.springframework.beans.factory.annotation.Value import org.springframework.stereotype.Service @@ -10,12 +9,9 @@ class UrlConversionService(private val cloudService: CloudService) { @Value("\${aws.folderForThemePictures}") private lateinit var folderForThemePictures: String - private val log = logger() - fun makeUrlForNoise(noiseUrl: String?): String { - if (noiseUrl.isNullOrEmpty()) - return "" - return cloudService.baseFileUrl() + noiseUrl + return if (noiseUrl.isNullOrEmpty()) "" + else cloudService.baseFileUrl() + noiseUrl } fun makeUrlForSubGroupPicture(subGroupCode: String): String = diff --git a/src/test/kotlin/com/epam/brn/integration/BaseIT.kt b/src/test/kotlin/com/epam/brn/integration/BaseIT.kt index d6cfde71c..daca94266 100644 --- a/src/test/kotlin/com/epam/brn/integration/BaseIT.kt +++ b/src/test/kotlin/com/epam/brn/integration/BaseIT.kt @@ -1,21 +1,25 @@ package com.epam.brn.integration -import com.epam.brn.model.Role +import com.epam.brn.enums.BrnGender import com.epam.brn.model.Exercise import com.epam.brn.model.ExerciseGroup -import com.epam.brn.enums.BrnGender +import com.epam.brn.model.Role import com.epam.brn.model.Series import com.epam.brn.model.StudyHistory import com.epam.brn.model.SubGroup import com.epam.brn.model.UserAccount -import com.epam.brn.repo.RoleRepository import com.epam.brn.repo.ExerciseGroupRepository import com.epam.brn.repo.ExerciseRepository +import com.epam.brn.repo.RoleRepository import com.epam.brn.repo.SeriesRepository import com.epam.brn.repo.StudyHistoryRepository import com.epam.brn.repo.SubGroupRepository +import com.epam.brn.repo.TaskRepository import com.epam.brn.repo.UserAccountRepository import com.fasterxml.jackson.databind.ObjectMapper +import java.time.LocalDateTime +import java.time.format.DateTimeFormatter +import java.time.temporal.ChronoUnit import org.amshove.kluent.internal.platformClassName import org.junit.jupiter.api.Tag import org.springframework.beans.factory.annotation.Autowired @@ -24,9 +28,6 @@ import org.springframework.boot.test.context.SpringBootTest import org.springframework.test.context.ActiveProfiles import org.springframework.test.web.servlet.MockMvc import org.testcontainers.junit.jupiter.Testcontainers -import java.time.LocalDateTime -import java.time.format.DateTimeFormatter -import java.time.temporal.ChronoUnit @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @AutoConfigureMockMvc @@ -43,22 +44,18 @@ abstract class BaseIT { @Autowired private lateinit var userAccountRepository: UserAccountRepository - @Autowired private lateinit var studyHistoryRepository: StudyHistoryRepository - @Autowired - private lateinit var exerciseRepository: ExerciseRepository - + private lateinit var exerciseGroupRepository: ExerciseGroupRepository + @Autowired + private lateinit var seriesRepository: SeriesRepository @Autowired private lateinit var subGroupRepository: SubGroupRepository - @Autowired - private lateinit var exerciseGroupRepository: ExerciseGroupRepository - + private lateinit var exerciseRepository: ExerciseRepository @Autowired - private lateinit var seriesRepository: SeriesRepository - + private lateinit var taskRepository: TaskRepository @Autowired private lateinit var roleRepository: RoleRepository diff --git a/src/test/kotlin/com/epam/brn/integration/ExercisesControllerIT.kt b/src/test/kotlin/com/epam/brn/integration/ExercisesControllerIT.kt index 49c6b9433..45202ae83 100644 --- a/src/test/kotlin/com/epam/brn/integration/ExercisesControllerIT.kt +++ b/src/test/kotlin/com/epam/brn/integration/ExercisesControllerIT.kt @@ -21,7 +21,6 @@ import com.epam.brn.repo.SeriesRepository import com.epam.brn.repo.StudyHistoryRepository import com.epam.brn.repo.SubGroupRepository import com.epam.brn.repo.UserAccountRepository -import com.google.gson.Gson import org.json.JSONObject import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.Assertions @@ -60,9 +59,6 @@ class ExercisesControllerIT : BaseIT() { @Autowired lateinit var exerciseGroupRepository: ExerciseGroupRepository - @Autowired - lateinit var gson: Gson - @AfterEach fun deleteAfterTest() { studyHistoryRepository.deleteAll() @@ -80,7 +76,7 @@ class ExercisesControllerIT : BaseIT() { val exerciseName = "ExerciseNameTest" val existingSeries = insertSeries() val subGroup = insertSubGroup(existingSeries) - val existingExercise = insertExercise(exerciseName, subGroup) + val existingExercise = insertExercise(subGroup, exerciseName) insertStudyHistory(existingUser, existingExercise, LocalDateTime.now().minusHours(1)) insertStudyHistory(existingUser, existingExercise, LocalDateTime.now()) // WHEN @@ -103,7 +99,7 @@ class ExercisesControllerIT : BaseIT() { val exerciseName = "ExerciseNameTest" val existingSeries = insertSeries() val subGroup = insertSubGroup(existingSeries) - val existingExercise = insertExercise(exerciseName, subGroup) + val existingExercise = insertExercise(subGroup, exerciseName) // WHEN val resultAction = mockMvc.perform( MockMvcRequestBuilders @@ -131,7 +127,7 @@ class ExercisesControllerIT : BaseIT() { val exerciseName = "ExerciseNameTest" val existingSeries = insertSeries() val subGroup = insertSubGroup(existingSeries) - val exercise = insertExercise(exerciseName, subGroup) + val exercise = insertExercise(subGroup, exerciseName) val requestJson: String = objectMapper.writeValueAsString(ExerciseRequest(listOf(exercise.id!!))) // WHEN val resultAction = mockMvc.perform( @@ -299,12 +295,11 @@ class ExercisesControllerIT : BaseIT() { ) } - private fun insertSubGroup(series: Series): SubGroup = subGroupRepository.save( - SubGroup(series = series, level = 1, code = "code", name = "subGroup name") - ) + private fun insertSubGroup(series: Series): SubGroup = + subGroupRepository.save(SubGroup(series = series, level = 1, code = "code", name = "subGroup name")) - fun insertExercise(exerciseName: String, subGroup: SubGroup): Exercise { - return exerciseRepository.save( + fun insertExercise(subGroup: SubGroup, exerciseName: String): Exercise = + exerciseRepository.save( Exercise( subGroup = subGroup, level = 0, @@ -313,13 +308,7 @@ class ExercisesControllerIT : BaseIT() { noiseUrl = "/testNoiseUrl" ) ) - } - fun insertExercise(exerciseName: String): Exercise { - return exerciseRepository.save( - Exercise( - name = exerciseName - ) - ) - } + fun insertExercise(exerciseName: String): Exercise = + exerciseRepository.save(Exercise(name = exerciseName)) } diff --git a/src/test/kotlin/com/epam/brn/integration/GroupControllerIT.kt b/src/test/kotlin/com/epam/brn/integration/GroupControllerIT.kt index c05560eaa..439600bf3 100644 --- a/src/test/kotlin/com/epam/brn/integration/GroupControllerIT.kt +++ b/src/test/kotlin/com/epam/brn/integration/GroupControllerIT.kt @@ -2,8 +2,17 @@ package com.epam.brn.integration import com.epam.brn.enums.BrnLocale import com.epam.brn.enums.BrnRole -import com.epam.brn.repo.ExerciseGroupRepository +import com.epam.brn.enums.ExerciseType +import com.epam.brn.model.Exercise import com.epam.brn.model.ExerciseGroup +import com.epam.brn.model.Series +import com.epam.brn.model.SubGroup +import com.epam.brn.model.Task +import com.epam.brn.repo.ExerciseGroupRepository +import com.epam.brn.repo.ExerciseRepository +import com.epam.brn.repo.SeriesRepository +import com.epam.brn.repo.SubGroupRepository +import com.epam.brn.repo.TaskRepository import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.Test @@ -21,35 +30,21 @@ class GroupControllerIT : BaseIT() { private val baseUrl = "/groups" @Autowired - lateinit var exerciseGroupRepository: ExerciseGroupRepository + private lateinit var exerciseGroupRepository: ExerciseGroupRepository + @Autowired + private lateinit var seriesRepository: SeriesRepository + @Autowired + private lateinit var subGroupRepository: SubGroupRepository + @Autowired + private lateinit var exerciseRepository: ExerciseRepository + @Autowired + private lateinit var taskRepository: TaskRepository @AfterEach fun deleteAfterTest() { exerciseGroupRepository.deleteAll() } - @Test - fun `test get all groups`() { - // GIVEN - val exerciseGroupName1 = "GroupName1" - val existingExerciseGroup1 = insertExerciseGroup(exerciseGroupName1) - val exerciseGroupName2 = "GroupName2" - val existingExerciseGroup2 = insertExerciseGroup(exerciseGroupName2) - // WHEN - val resultAction = mockMvc.perform( - MockMvcRequestBuilders - .get(baseUrl) - .contentType(MediaType.APPLICATION_JSON) - ) - // THEN - resultAction - .andExpect(status().isOk) - .andExpect(MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON)) - val response = resultAction.andReturn().response.contentAsString - assertTrue(response.contains(existingExerciseGroup1.name)) - assertTrue(response.contains(existingExerciseGroup2.name)) - } - @Test fun `test find ru groups`() { // GIVEN @@ -57,6 +52,12 @@ class GroupControllerIT : BaseIT() { val groupRu = insertExerciseGroup(exerciseGroupName1, BrnLocale.RU.locale) val exerciseGroupName2 = "GroupName2" val groupEn = insertExerciseGroup(exerciseGroupName2, BrnLocale.EN.locale) + val series1 = insertSeries(groupRu, "series1Name") + val series2 = insertSeries(groupRu, "series2Name") + val subGroup1 = insertSubGroup(series1, 1) + val subGroup2 = insertSubGroup(series1, 2) + val exercise = insertExercise(subGroup1, "ex1") + val task = insertTask(exercise) // WHEN val resultAction = mockMvc.perform( MockMvcRequestBuilders @@ -92,8 +93,8 @@ class GroupControllerIT : BaseIT() { assertTrue(response.contains(existingExerciseGroup.name)) } - private fun insertExerciseGroup(exerciseGroupName: String, locale: String = BrnLocale.RU.locale): ExerciseGroup { - return exerciseGroupRepository.save( + fun insertExerciseGroup(exerciseGroupName: String, locale: String = BrnLocale.RU.locale): ExerciseGroup = + exerciseGroupRepository.save( ExerciseGroup( code = "CODE", description = "desc", @@ -101,5 +102,46 @@ class GroupControllerIT : BaseIT() { locale = locale ) ) + + fun insertSeries(group: ExerciseGroup, name: String): Series { + val series = Series( + name = name, + description = "description", + exerciseGroup = group, + level = 1, + type = ExerciseType.SINGLE_SIMPLE_WORDS.name + ) + return seriesRepository.save(series) } + + fun insertSubGroup(series: Series, level: Int): SubGroup = + subGroupRepository.save( + SubGroup( + series = series, + level = level, + code = "code", + name = "${series.name}subGroupName$level" + ) + ) + + fun insertExercise(subGroup: SubGroup, exerciseName: String): Exercise = + exerciseRepository.save( + Exercise( + subGroup = subGroup, + level = 0, + name = exerciseName, + noiseLevel = 50, + noiseUrl = "/testNoiseUrl" + ) + ) + + fun insertTask(exercise: Exercise): Task = + taskRepository.save( + Task( + id = 1, + name = "${exercise.name} Task", + serialNumber = 1, + exercise = exercise + ) + ) } diff --git a/src/test/kotlin/com/epam/brn/integration/SeriesControllerIT.kt b/src/test/kotlin/com/epam/brn/integration/SeriesControllerIT.kt index 42732f58a..4fe5a9244 100644 --- a/src/test/kotlin/com/epam/brn/integration/SeriesControllerIT.kt +++ b/src/test/kotlin/com/epam/brn/integration/SeriesControllerIT.kt @@ -5,8 +5,8 @@ import com.epam.brn.repo.SeriesRepository import com.epam.brn.dto.SeriesDto import com.epam.brn.dto.response.BrnResponse import com.epam.brn.enums.BrnRole -import com.epam.brn.model.ExerciseGroup import com.epam.brn.enums.ExerciseType +import com.epam.brn.model.ExerciseGroup import com.epam.brn.model.Series import com.fasterxml.jackson.core.type.TypeReference import com.google.gson.Gson @@ -47,11 +47,6 @@ class SeriesControllerIT : BaseIT() { return exerciseGroupRepository.save(group) } - private fun insertSeries(group: ExerciseGroup, name: String): Series { - val series = Series(name = name, description = "description", exerciseGroup = group, level = 1, type = ExerciseType.SINGLE_SIMPLE_WORDS.name) - return seriesRepository.save(series) - } - @Test fun `test get series for group`() { // GIVEN @@ -120,4 +115,15 @@ class SeriesControllerIT : BaseIT() { Assertions.assertTrue(response.contains("1,family,Семья,(сын ребёнок мама),0,")) Assertions.assertEquals(expectedResponse, response) } + + fun insertSeries(group: ExerciseGroup, name: String): Series { + val series = Series( + name = name, + description = "description", + exerciseGroup = group, + level = 1, + type = ExerciseType.SINGLE_SIMPLE_WORDS.name + ) + return seriesRepository.save(series) + } } diff --git a/src/test/kotlin/com/epam/brn/integration/SubGroupControllerIT.kt b/src/test/kotlin/com/epam/brn/integration/SubGroupControllerIT.kt index c03346756..af96efd0b 100644 --- a/src/test/kotlin/com/epam/brn/integration/SubGroupControllerIT.kt +++ b/src/test/kotlin/com/epam/brn/integration/SubGroupControllerIT.kt @@ -95,8 +95,7 @@ class SubGroupControllerIT : BaseIT() { .contentType(MediaType.APPLICATION_JSON) ) // THEN - resultAction - .andExpect(status().isOk) + resultAction.andExpect(status().isOk) } @Test @@ -115,7 +114,10 @@ class SubGroupControllerIT : BaseIT() { resultAction .andExpect(status().isBadRequest) .andExpect(MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON)) - .andExpect(MockMvcResultMatchers.content().string(containsString("Can not delete subGroup because there are exercises that refer to the subGroup."))) + .andExpect( + MockMvcResultMatchers.content() + .string(containsString("Can not delete subGroup because there are exercises that refer to the subGroup.")) + ) } @Test @@ -133,7 +135,10 @@ class SubGroupControllerIT : BaseIT() { resultAction .andExpect(status().isBadRequest) .andExpect(MockMvcResultMatchers.content().contentType(MediaType.APPLICATION_JSON)) - .andExpect(MockMvcResultMatchers.content().string(containsString("Can not delete subGroup because subGroup is not found by this id."))) + .andExpect( + MockMvcResultMatchers.content() + .string(containsString("Can not delete subGroup because subGroup is not found by this id.")) + ) } @Test diff --git a/src/test/kotlin/com/epam/brn/integration/TaskControllerIT.kt b/src/test/kotlin/com/epam/brn/integration/TaskControllerIT.kt index c4016c135..21badcbb6 100644 --- a/src/test/kotlin/com/epam/brn/integration/TaskControllerIT.kt +++ b/src/test/kotlin/com/epam/brn/integration/TaskControllerIT.kt @@ -5,13 +5,13 @@ import com.epam.brn.repo.ExerciseGroupRepository import com.epam.brn.repo.ExerciseRepository import com.epam.brn.repo.SeriesRepository import com.epam.brn.repo.SubGroupRepository -import com.epam.brn.repo.TaskRepository import com.epam.brn.model.Exercise import com.epam.brn.model.ExerciseGroup import com.epam.brn.enums.ExerciseType import com.epam.brn.model.Series import com.epam.brn.model.SubGroup import com.epam.brn.model.Task +import com.epam.brn.repo.TaskRepository import org.json.JSONObject import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.Assertions @@ -27,20 +27,16 @@ import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status @WithMockUser(username = "test@test.test", roles = [BrnRole.USER]) class TaskControllerIT : BaseIT() { - @Autowired - lateinit var taskRepository: TaskRepository - @Autowired lateinit var exerciseRepository: ExerciseRepository - @Autowired lateinit var subGroupRepository: SubGroupRepository - @Autowired lateinit var seriesRepository: SeriesRepository - @Autowired lateinit var exerciseGroupRepository: ExerciseGroupRepository + @Autowired + private lateinit var taskRepository: TaskRepository lateinit var exercise: Exercise @@ -145,8 +141,8 @@ class TaskControllerIT : BaseIT() { ) } - private fun insertTask(exercise: Exercise): Task { - return taskRepository.save( + private fun insertTask(exercise: Exercise): Task = + taskRepository.save( Task( id = 1, name = "${exercise.name} Task", @@ -154,5 +150,4 @@ class TaskControllerIT : BaseIT() { exercise = exercise ) ) - } } diff --git a/src/test/kotlin/com/epam/brn/service/ExerciseGroupServiceTest.kt b/src/test/kotlin/com/epam/brn/service/ExerciseGroupServiceTest.kt index 4358d76b4..14a11a370 100644 --- a/src/test/kotlin/com/epam/brn/service/ExerciseGroupServiceTest.kt +++ b/src/test/kotlin/com/epam/brn/service/ExerciseGroupServiceTest.kt @@ -10,11 +10,11 @@ import io.mockk.impl.annotations.MockK import io.mockk.junit5.MockKExtension import io.mockk.mockk import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith import java.util.Optional import kotlin.test.assertFailsWith +import org.amshove.kluent.`should be` @ExtendWith(MockKExtension::class) internal class ExerciseGroupServiceTest { @@ -24,20 +24,6 @@ internal class ExerciseGroupServiceTest { @InjectMockKs lateinit var exerciseGroupsService: ExerciseGroupsService - @Test - fun `should get all groups`() { - // GIVEN - val exerciseGroupMock: ExerciseGroup = mockk(relaxed = true) - val exerciseGroupDtoMock = ExerciseGroupDto(id = 1, locale = "en", name = "name", description = "descr") - - every { exerciseGroupMock.toDto() } returns (exerciseGroupDtoMock) - every { exerciseGroupRepository.findAll() } returns (listOf(exerciseGroupMock)) - // WHEN - val actualResult: List = exerciseGroupsService.findAllGroups() - // THEN - assertTrue(actualResult.contains(exerciseGroupDtoMock)) - } - @Test fun `should get group by id`() { // GIVEN @@ -65,6 +51,21 @@ internal class ExerciseGroupServiceTest { assertEquals(actualResult, exerciseGroupMock) } + @Test + fun `should get group by locale if it's exists`() { + // GIVEN + val locale = "ru-ru" + val exerciseGroupMock = + ExerciseGroup(id = 1, code = "groupCode", locale = "ru-ru", name = "name", description = "descr") + every { exerciseGroupRepository.findByLocale(locale) } returns listOf(exerciseGroupMock) + // WHEN + val actualResult: List = exerciseGroupsService.findByLocale(locale) + // THEN + actualResult.isNotEmpty() + actualResult.first().id `should be` 1 + actualResult.first().locale `should be` "ru-ru" + } + @Test fun `should throw error when find group by not exist code`() { // GIVEN