From a891affc0d2f110a96302321269cc03bf72df09e Mon Sep 17 00:00:00 2001 From: Marcin Bator Date: Sat, 7 Dec 2024 15:51:07 +0100 Subject: [PATCH] feat: #185 GradeStore and CategoryStore unit tests --- .../kodemycommons/util/PrincipalUtil.java | 14 ++ .../configuration/WebConfiguration.java | 6 + .../infrastructure/store/GradeStore.java | 12 +- .../store/CategoryStoreSpec.groovy | 34 ++++ .../store/GradeStoreSpec.groovy | 157 ++++++++++++++++++ 5 files changed, 216 insertions(+), 7 deletions(-) create mode 100644 commons/src/main/java/pl/sknikod/kodemycommons/util/PrincipalUtil.java create mode 100644 kodemy-backend/src/test/groovy/unit/infrastructure/store/CategoryStoreSpec.groovy create mode 100644 kodemy-backend/src/test/groovy/unit/infrastructure/store/GradeStoreSpec.groovy diff --git a/commons/src/main/java/pl/sknikod/kodemycommons/util/PrincipalUtil.java b/commons/src/main/java/pl/sknikod/kodemycommons/util/PrincipalUtil.java new file mode 100644 index 00000000..901131bf --- /dev/null +++ b/commons/src/main/java/pl/sknikod/kodemycommons/util/PrincipalUtil.java @@ -0,0 +1,14 @@ +package pl.sknikod.kodemycommons.util; + +import org.springframework.stereotype.Component; +import pl.sknikod.kodemycommons.security.AuthFacade; +import pl.sknikod.kodemycommons.security.UserPrincipal; + +import java.util.Optional; + +@Component +public class PrincipalUtil { + public Optional getPrincipal(){ + return AuthFacade.getCurrentUserPrincipal(); + } +} diff --git a/kodemy-backend/src/main/java/pl/sknikod/kodemybackend/configuration/WebConfiguration.java b/kodemy-backend/src/main/java/pl/sknikod/kodemybackend/configuration/WebConfiguration.java index 85ebfa59..ce6ab043 100644 --- a/kodemy-backend/src/main/java/pl/sknikod/kodemybackend/configuration/WebConfiguration.java +++ b/kodemy-backend/src/main/java/pl/sknikod/kodemybackend/configuration/WebConfiguration.java @@ -8,6 +8,7 @@ import pl.sknikod.kodemycommons.exception.handler.RestExceptionHandler; import pl.sknikod.kodemycommons.network.LanRestTemplate; import pl.sknikod.kodemycommons.security.JwtProvider; +import pl.sknikod.kodemycommons.util.PrincipalUtil; @Configuration public class WebConfiguration { @@ -30,4 +31,9 @@ public LanRestTemplate lanRestTemplate( ) { return new LanRestTemplate(connectTimeoutMs, readTimeoutMs, jwtProvider); } + + @Bean + public PrincipalUtil principalUtil(){ + return new PrincipalUtil(); + } } diff --git a/kodemy-backend/src/main/java/pl/sknikod/kodemybackend/infrastructure/store/GradeStore.java b/kodemy-backend/src/main/java/pl/sknikod/kodemybackend/infrastructure/store/GradeStore.java index 5cf09eeb..f1aca30b 100644 --- a/kodemy-backend/src/main/java/pl/sknikod/kodemybackend/infrastructure/store/GradeStore.java +++ b/kodemy-backend/src/main/java/pl/sknikod/kodemybackend/infrastructure/store/GradeStore.java @@ -16,16 +16,13 @@ import pl.sknikod.kodemybackend.infrastructure.database.GradeRepository; import pl.sknikod.kodemybackend.infrastructure.database.Material; import pl.sknikod.kodemybackend.infrastructure.database.MaterialRepository; +import pl.sknikod.kodemycommons.util.PrincipalUtil; import pl.sknikod.kodemycommons.exception.NotFound404Exception; import pl.sknikod.kodemycommons.exception.content.ExceptionMsgPattern; -import pl.sknikod.kodemycommons.security.AuthFacade; import java.time.LocalDateTime; import java.time.ZoneId; -import java.util.Collection; -import java.util.Date; -import java.util.HashSet; -import java.util.List; +import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -36,6 +33,7 @@ public class GradeStore { private final GradeRepository gradeRepository; private final UserStore userStore; private final MaterialRepository materialRepository; + private final PrincipalUtil principalUtil; public Try findAvgGradeByMaterial(Long id) { return Try.of(() -> gradeRepository.findAvgGradeByMaterialId(id)); @@ -95,7 +93,7 @@ public Try addGrade(Long materialId, double value) { ExceptionMsgPattern.ENTITY_NOT_FOUND_BY_PARAM, Material.class.getSimpleName(), "id", materialId ); }) - .mapTry(unused -> new Grade(value, AuthFacade.getCurrentUserPrincipal().get().getId(), materialId)) + .mapTry(unused -> new Grade(value, principalUtil.getPrincipal().get().getId(), materialId)) .map(gradeRepository::save) .onFailure(th -> log.error("Cannot add grade", th)); } @@ -116,5 +114,5 @@ public FindAvgGradeObject(Object[] objects) { this.materialId = (Long) objects[0]; this.avgGrade = (Double) objects[1]; } - } + } } diff --git a/kodemy-backend/src/test/groovy/unit/infrastructure/store/CategoryStoreSpec.groovy b/kodemy-backend/src/test/groovy/unit/infrastructure/store/CategoryStoreSpec.groovy new file mode 100644 index 00000000..19ab44a0 --- /dev/null +++ b/kodemy-backend/src/test/groovy/unit/infrastructure/store/CategoryStoreSpec.groovy @@ -0,0 +1,34 @@ +package unit.infrastructure.store + +import org.spockframework.util.Assert +import pl.sknikod.kodemybackend.infrastructure.database.Category +import pl.sknikod.kodemybackend.infrastructure.database.CategoryRepository +import pl.sknikod.kodemybackend.infrastructure.store.CategoryStore +import pl.sknikod.kodemycommons.exception.NotFound404Exception +import spock.lang.Specification + +class CategoryStoreSpec extends Specification{ + def categoryRepository = Mock(CategoryRepository) + + def categoryStore = new CategoryStore(categoryRepository) + + private static final CATEGORY_ID = 1L + + def "shouldFindCategoryById" () { + given: + categoryRepository.findById(CATEGORY_ID) >> Optional.of(new Category()) + when: + def result = categoryStore.findById(CATEGORY_ID) + then: + Assert.that(!result.isEmpty()) + } + + def "shouldThrowNotFoundWhenFindCategoryById" () { + given: + categoryRepository.findById(CATEGORY_ID) >> Optional.empty() + when: + categoryStore.findById(CATEGORY_ID).get() + then: + thrown(NotFound404Exception) + } +} diff --git a/kodemy-backend/src/test/groovy/unit/infrastructure/store/GradeStoreSpec.groovy b/kodemy-backend/src/test/groovy/unit/infrastructure/store/GradeStoreSpec.groovy new file mode 100644 index 00000000..f96090c7 --- /dev/null +++ b/kodemy-backend/src/test/groovy/unit/infrastructure/store/GradeStoreSpec.groovy @@ -0,0 +1,157 @@ +package unit.infrastructure.store + +import io.vavr.control.Try +import org.spockframework.util.Assert +import org.springframework.data.domain.PageImpl +import org.springframework.data.domain.PageRequest +import org.springframework.security.core.authority.SimpleGrantedAuthority +import pl.sknikod.kodemybackend.infrastructure.database.Grade +import pl.sknikod.kodemybackend.infrastructure.database.GradeRepository +import pl.sknikod.kodemybackend.infrastructure.database.MaterialRepository +import pl.sknikod.kodemybackend.infrastructure.store.GradeStore +import pl.sknikod.kodemybackend.infrastructure.store.UserStore +import pl.sknikod.kodemycommons.exception.NotFound404Exception +import pl.sknikod.kodemycommons.security.UserPrincipal +import pl.sknikod.kodemycommons.util.PrincipalUtil +import spock.lang.Specification + +import java.time.LocalDateTime +import java.time.ZoneId + +class GradeStoreSpec extends Specification { + def gradeRepository = Mock(GradeRepository) + def userStore = Mock(UserStore) + def materialRepository = Mock(MaterialRepository) + def principalUtil = Mock(PrincipalUtil) + + def gradeStore = new GradeStore(gradeRepository, userStore, materialRepository, principalUtil) + + private static final MATERIAL_ID = 1L + private static final GRADE = 3.0 + private static final USER_ID = 1L + + def "shouldFindAvgGradeByMaterialId"() { + given: + gradeRepository.findAvgGradeByMaterialId(MATERIAL_ID) >> GRADE + when: + def result = gradeStore.findAvgGradeByMaterial(MATERIAL_ID).get() + then: + Assert.that(result == 3.0) + } + + def "shouldGetGradeStatsByMaterialId"() { + given: + gradeRepository.countAllByMaterialIdAndValue(MATERIAL_ID, 1.0) + >> 0L + gradeRepository.countAllByMaterialIdAndValue(MATERIAL_ID, 2.0) + >> 0L + gradeRepository.countAllByMaterialIdAndValue(MATERIAL_ID, GRADE) + >> 1L + gradeRepository.countAllByMaterialIdAndValue(MATERIAL_ID, 4.0) + >> 0L + gradeRepository.countAllByMaterialIdAndValue(MATERIAL_ID, 5.0) + >> 0L + when: + def result = gradeStore.getGradeStats(MATERIAL_ID).get() + then: + Assert.that(result == List.of(0L, 0L, 1L, 0L, 0L)) + } + + def "shouldSaveGrade"() { + given: + def grade = new Grade() + gradeRepository.save(_ as Grade) >> grade + when: + def result = gradeStore.save(grade).get() + then: + Assert.that(grade == result) + } + + def "shouldFindGradesByMaterialInDateRange"() { + given: + def grades = List.of( + new Grade(GRADE, USER_ID, MATERIAL_ID) + ) + def user = new UserStore.User() + user.id = USER_ID + user.username = "name" + + gradeRepository.findGradesByMaterialInDateRange( + MATERIAL_ID, + _ as LocalDateTime, + _ as LocalDateTime, + _ as PageRequest + ) >> new PageImpl(grades) + userStore.findUsersById(_ as Set) >> Try.success(new ArrayList<>(List.of(user))) + when: + def result = gradeStore.findGradesByMaterialInDateRange( + MATERIAL_ID, + Date.from(LocalDateTime.now().minusDays(1).atZone(ZoneId.systemDefault()).toInstant()), + Date.from(LocalDateTime.now().plusDays(1).atZone(ZoneId.systemDefault()).toInstant()), + PageRequest.of(1, 1,) + ).get() + then: + verifyAll(result) { + result._1() == new PageImpl(grades) + result._2() == Set.of(user) + } + } + + def "shouldThrowWhenFindGradesByMaterialInDateRange"() { + given: + def grades = List.of( + new Grade(GRADE, USER_ID, MATERIAL_ID) + ) + + gradeRepository.findGradesByMaterialInDateRange( + MATERIAL_ID, + _ as LocalDateTime, + _ as LocalDateTime, + _ as PageRequest + ) >> new PageImpl(grades) + userStore.findUsersById(_ as Set) >> Try.success(new ArrayList<>()) + when: + gradeStore.findGradesByMaterialInDateRange( + MATERIAL_ID, + Date.from(LocalDateTime.now().minusDays(1).atZone(ZoneId.systemDefault()).toInstant()), + Date.from(LocalDateTime.now().plusDays(1).atZone(ZoneId.systemDefault()).toInstant()), + PageRequest.of(1, 1,) + ).get() + then: + thrown(IllegalStateException) + } + + def "shouldAddGrade"() { + given: + def grade = new Grade(GRADE, USER_ID, MATERIAL_ID) + materialRepository.existsById(MATERIAL_ID) >> true + gradeRepository.save(_ as Grade) >> grade + principalUtil.getPrincipal() >> Optional.of(new UserPrincipal( + USER_ID, "", false, false, + false, true, new HashSet() + )) + when: + def result = gradeStore.addGrade(MATERIAL_ID, GRADE).get() + then: + Assert.that(grade == result) + } + + def "shouldThrowWhenAddGrade"() { + given: + materialRepository.existsById(MATERIAL_ID) >> false + when: + gradeStore.addGrade(MATERIAL_ID, GRADE).get() + then: + thrown(NotFound404Exception) + } + + def "shouldFindAvgGradeByMaterialsIds"() { + given: + gradeRepository.findAvgGradeByMaterialsIds(_ as List) + >> new HashSet() + when: + def result = gradeStore.findAvgGradeByMaterialsIds(List.of(1L)).get() + then: + Assert.that(result in List) + } +}