diff --git a/simulator-spring-boot/lombok.config b/simulator-spring-boot/lombok.config new file mode 100644 index 000000000..a330a9077 --- /dev/null +++ b/simulator-spring-boot/lombok.config @@ -0,0 +1 @@ +lombok.log.fieldName = logger diff --git a/simulator-spring-boot/src/main/java/org/citrusframework/simulator/repository/MessageRepository.java b/simulator-spring-boot/src/main/java/org/citrusframework/simulator/repository/MessageRepository.java index 59d71307e..36618765f 100644 --- a/simulator-spring-boot/src/main/java/org/citrusframework/simulator/repository/MessageRepository.java +++ b/simulator-spring-boot/src/main/java/org/citrusframework/simulator/repository/MessageRepository.java @@ -16,6 +16,8 @@ package org.citrusframework.simulator.repository; +import java.util.List; +import java.util.Optional; import org.citrusframework.simulator.model.Message; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -27,9 +29,6 @@ import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; -import java.util.List; -import java.util.Optional; - /** * Spring Data JPA repository for the {@link Message} entity. */ @@ -62,4 +61,8 @@ default List findAllForScenarioExecution(Long scenarioExecutionId, Stri } List findAllByScenarioExecutionExecutionIdEqualsAndCitrusMessageIdEqualsIgnoreCaseAndDirectionEquals(@Param("scenarioExecutionId") Long scenarioExecutionId, @Param("citrusMessageId") String citrusMessageId, @Param("direction") Integer direction); + + @Query("FROM Message WHERE messageId IN :messageIds") + @EntityGraph(attributePaths = {"headers", "scenarioExecution"}) + Page findAllWhereIdIn(@Param("messageIds") List messageIds, Pageable pageable); } diff --git a/simulator-spring-boot/src/main/java/org/citrusframework/simulator/repository/ScenarioExecutionRepository.java b/simulator-spring-boot/src/main/java/org/citrusframework/simulator/repository/ScenarioExecutionRepository.java index f5a3dca8e..8966555e4 100644 --- a/simulator-spring-boot/src/main/java/org/citrusframework/simulator/repository/ScenarioExecutionRepository.java +++ b/simulator-spring-boot/src/main/java/org/citrusframework/simulator/repository/ScenarioExecutionRepository.java @@ -16,18 +16,19 @@ package org.citrusframework.simulator.repository; +import java.util.List; +import java.util.Optional; +import java.util.Set; import org.citrusframework.simulator.model.ScenarioExecution; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; -import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.repository.EntityGraph; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; -import java.util.Optional; - /** * Spring Data JPA repository for the {@link ScenarioExecution} entity. */ @@ -38,10 +39,10 @@ public interface ScenarioExecutionRepository extends JpaRepository findAll(Pageable pageable); - @Override @EntityGraph(attributePaths = {"scenarioParameters", "scenarioActions", "scenarioMessages"}) - Page findAll(Specification spec, Pageable pageable); + Optional findOneByExecutionId(@Param("executionId") Long executionId); + @Query("FROM ScenarioExecution WHERE executionId IN :scenarioExecutionIds") @EntityGraph(attributePaths = {"scenarioParameters", "scenarioActions", "scenarioMessages"}) - Optional findOneByExecutionId(@Param("executionId") Long executionId); + Page findAllWhereIdIn(@Param("scenarioExecutionIds") List scenarioExecutionIds, Pageable pageable); } diff --git a/simulator-spring-boot/src/main/java/org/citrusframework/simulator/repository/TestResultRepository.java b/simulator-spring-boot/src/main/java/org/citrusframework/simulator/repository/TestResultRepository.java index ecef57a3e..3c343bffd 100644 --- a/simulator-spring-boot/src/main/java/org/citrusframework/simulator/repository/TestResultRepository.java +++ b/simulator-spring-boot/src/main/java/org/citrusframework/simulator/repository/TestResultRepository.java @@ -16,19 +16,19 @@ package org.citrusframework.simulator.repository; +import java.util.List; +import java.util.Optional; import org.citrusframework.simulator.model.TestResult; import org.citrusframework.simulator.service.dto.TestResultByStatus; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; -import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.repository.EntityGraph; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; -import java.util.Optional; - /** * Spring Data JPA repository for the {@link TestResult} entity. */ @@ -47,9 +47,9 @@ public interface TestResultRepository extends JpaRepository, J @Override @EntityGraph(attributePaths = {"testParameters"}) - Page findAll(Specification spec, Pageable pageable); + Optional findById(Long id); - @Override + @Query("FROM TestResult WHERE id IN :testResultIds") @EntityGraph(attributePaths = {"testParameters"}) - Optional findById(Long id); + Page findAllWhereIdIn(@Param("testResultIds") List testResultIds, Pageable pageable); } diff --git a/simulator-spring-boot/src/main/java/org/citrusframework/simulator/service/CriteriaQueryUtils.java b/simulator-spring-boot/src/main/java/org/citrusframework/simulator/service/CriteriaQueryUtils.java new file mode 100644 index 000000000..806fc3ef3 --- /dev/null +++ b/simulator-spring-boot/src/main/java/org/citrusframework/simulator/service/CriteriaQueryUtils.java @@ -0,0 +1,130 @@ +/* + * Copyright 2024 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.citrusframework.simulator.service; + +import static java.util.Objects.nonNull; + +import jakarta.persistence.EntityManager; +import jakarta.persistence.TypedQuery; +import jakarta.persistence.criteria.CriteriaBuilder; +import jakarta.persistence.criteria.CriteriaQuery; +import jakarta.persistence.criteria.Order; +import jakarta.persistence.criteria.Predicate; +import jakarta.persistence.criteria.Root; +import jakarta.persistence.metamodel.SingularAttribute; +import java.util.ArrayList; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.domain.Specification; + +final class CriteriaQueryUtils { + + private CriteriaQueryUtils() { + // Static utility class + } + + /** + * There is an issue within Hibernate when trying to apply {@link Pageable} in combination with filtering through + * a {@link Specification}. Hibernate cannot create a query (although SQL would allow it) that returns the paginated + * result. We must therefore manually execute two (or rather three) queries: + *
    + *
  • The first query to fetch a paginated list of all entity ID's
  • + *
  • The second query, to fetch all entities that belong to those ID's
  • + *
  • And a third "count"-query, in order to retrieve the missing piece of pagination information
  • + *
+ *

+ * The warning is being seen in the log: + *

+     * [TIMESTAMP]: HHH90003004: firstResult/maxResults specified with collection fetch; applying in memory
+     * 
+ *

+ * The query created and returned by this function is the first of the mentioned queries, constructed with the + * restrictions from a given {@link Specification}. + * + * @see problem with in-memory pagination when having high volume of data + */ + static TypedQuery newSelectIdBySpecificationQuery(Class entityClass, SingularAttribute idAttribute, Specification specification, Pageable page, EntityManager entityManager) { + CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(Long.class); + Root root = criteriaQuery.from(entityClass); + + criteriaQuery = selectIdField(idAttribute, criteriaQuery, root); + + criteriaQuery = whereSpecificationApplies(specification, root, criteriaQuery, criteriaBuilder); + + criteriaQuery = orderByPageSort(page, root, criteriaBuilder, criteriaQuery); + + TypedQuery query = entityManager.createQuery(criteriaQuery); + query = selectPage(page, query); + + return query; + } + + /** + * Restrict the query to the ID of the entity. + * + * @return the modified {@link CriteriaQuery}. + */ + private static CriteriaQuery selectIdField(SingularAttribute idAttribute, CriteriaQuery criteriaQuery, Root root) { + return criteriaQuery.select(root.get(idAttribute)); + } + + /** + * Apply the specifications (criteria) to the query, if any restrictions exist. + * + * @return the modified {@link CriteriaQuery}. + */ + private static CriteriaQuery whereSpecificationApplies(Specification specification, Root root, CriteriaQuery criteriaQuery, CriteriaBuilder criteriaBuilder) { + Predicate predicate = specification.toPredicate(root, criteriaQuery, criteriaBuilder); + if (nonNull(predicate)) { + return criteriaQuery.where(predicate); + } + return criteriaQuery; + } + + /** + * Handle sorting, according to the definition of the {@link Pageable}. + * + * @return the modified {@link CriteriaQuery}. + */ + private static CriteriaQuery orderByPageSort(Pageable page, Root root, CriteriaBuilder criteriaBuilder, CriteriaQuery criteriaQuery) { + var orders = new ArrayList(); + for (var sortOrder : page.getSort()) { + var path = root.get(sortOrder.getProperty()); + orders.add(sortOrder.isAscending() ? criteriaBuilder.asc(path) : criteriaBuilder.desc(path)); + } + if (!orders.isEmpty()) { + return criteriaQuery.orderBy(orders); + } + return criteriaQuery; + } + + /** + * Apply pagination. + * + * @return The same {@link TypedQuery}. + */ + private static TypedQuery selectPage(Pageable page, TypedQuery query) { + // Calculate the first result index based on the page number and page size + var pageSize = page.getPageSize(); + var firstResult = page.getPageNumber() * pageSize; + + query = query.setFirstResult(firstResult); + query = query.setMaxResults(pageSize); + + return query; + } +} diff --git a/simulator-spring-boot/src/main/java/org/citrusframework/simulator/service/MessageQueryService.java b/simulator-spring-boot/src/main/java/org/citrusframework/simulator/service/MessageQueryService.java index 3a64b11c0..df3918d53 100644 --- a/simulator-spring-boot/src/main/java/org/citrusframework/simulator/service/MessageQueryService.java +++ b/simulator-spring-boot/src/main/java/org/citrusframework/simulator/service/MessageQueryService.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2023-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,38 +16,41 @@ package org.citrusframework.simulator.service; +import static org.citrusframework.simulator.service.CriteriaQueryUtils.newSelectIdBySpecificationQuery; + +import jakarta.persistence.EntityManager; import jakarta.persistence.criteria.JoinType; +import java.util.List; +import lombok.extern.slf4j.Slf4j; import org.citrusframework.simulator.model.Message; import org.citrusframework.simulator.model.MessageHeader_; import org.citrusframework.simulator.model.Message_; import org.citrusframework.simulator.model.ScenarioExecution_; import org.citrusframework.simulator.repository.MessageRepository; import org.citrusframework.simulator.service.criteria.MessageCriteria; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.domain.Specification; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.List; - /** * Service for executing complex queries for {@link Message} entities in the database. * The main input is a {@link MessageCriteria} which gets converted to {@link Specification}, * in a way that all the filters must apply. * It returns a {@link List} of {@link Message} or a {@link Page} of {@link Message} which fulfills the criteria. */ +@Slf4j @Service @Transactional(readOnly = true) public class MessageQueryService extends QueryService { - private static final Logger logger = LoggerFactory.getLogger(MessageQueryService.class); - + private final EntityManager entityManager; private final MessageRepository messageRepository; - public MessageQueryService(MessageRepository messageRepository) { + public MessageQueryService(EntityManager entityManager, MessageRepository messageRepository) { + this.entityManager = entityManager; this.messageRepository = messageRepository; } @@ -60,8 +63,19 @@ public MessageQueryService(MessageRepository messageRepository) { @Transactional(readOnly = true) public Page findByCriteria(MessageCriteria criteria, Pageable page) { logger.debug("find by criteria : {}, page: {}", criteria, page); - final Specification specification = createSpecification(criteria); - return messageRepository.findAll(specification, page); + + var specification = createSpecification(criteria); + var messageIds = newSelectIdBySpecificationQuery( + Message.class, + Message_.messageId, + specification, + page, + entityManager + ) + .getResultList(); + + var messages = messageRepository.findAllWhereIdIn(messageIds, page); + return new PageImpl<>(messages.getContent(), page, messageRepository.count(specification)); } /** diff --git a/simulator-spring-boot/src/main/java/org/citrusframework/simulator/service/ScenarioExecutionQueryService.java b/simulator-spring-boot/src/main/java/org/citrusframework/simulator/service/ScenarioExecutionQueryService.java index b6f84e520..f8adc2d28 100644 --- a/simulator-spring-boot/src/main/java/org/citrusframework/simulator/service/ScenarioExecutionQueryService.java +++ b/simulator-spring-boot/src/main/java/org/citrusframework/simulator/service/ScenarioExecutionQueryService.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2023-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,7 +16,12 @@ package org.citrusframework.simulator.service; +import static org.citrusframework.simulator.service.CriteriaQueryUtils.newSelectIdBySpecificationQuery; + +import jakarta.persistence.EntityManager; import jakarta.persistence.criteria.JoinType; +import java.util.List; +import lombok.extern.slf4j.Slf4j; import org.citrusframework.simulator.model.Message_; import org.citrusframework.simulator.model.ScenarioAction_; import org.citrusframework.simulator.model.ScenarioExecution; @@ -24,31 +29,29 @@ import org.citrusframework.simulator.model.ScenarioParameter_; import org.citrusframework.simulator.repository.ScenarioExecutionRepository; import org.citrusframework.simulator.service.criteria.ScenarioExecutionCriteria; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.domain.Specification; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.List; - /** * Service for executing complex queries for {@link ScenarioExecution} entities in the database. * The main input is a {@link ScenarioExecutionCriteria} which gets converted to {@link Specification}, * in a way that all the filters must apply. * It returns a {@link List} of {@link ScenarioExecution} or a {@link Page} of {@link ScenarioExecution} which fulfills the criteria. */ +@Slf4j @Service @Transactional(readOnly = true) public class ScenarioExecutionQueryService extends QueryService { - private static final Logger logger = LoggerFactory.getLogger(ScenarioExecutionQueryService.class); - + private final EntityManager entityManager; private final ScenarioExecutionRepository scenarioExecutionRepository; - public ScenarioExecutionQueryService(ScenarioExecutionRepository scenarioExecutionRepository) { + public ScenarioExecutionQueryService(EntityManager entityManager, ScenarioExecutionRepository scenarioExecutionRepository) { + this.entityManager = entityManager; this.scenarioExecutionRepository = scenarioExecutionRepository; } @@ -75,8 +78,19 @@ public List findByCriteria(ScenarioExecutionCriteria criteria @Transactional(readOnly = true) public Page findByCriteria(ScenarioExecutionCriteria criteria, Pageable page) { logger.debug("find by criteria : {}, page: {}", criteria, page); - final Specification specification = createSpecification(criteria); - return scenarioExecutionRepository.findAll(specification, page); + + var specification = createSpecification(criteria); + var scenarioExecutionIds = newSelectIdBySpecificationQuery( + ScenarioExecution.class, + ScenarioExecution_.executionId, + specification, + page, + entityManager + ) + .getResultList(); + + var scenarioExecutions = scenarioExecutionRepository.findAllWhereIdIn(scenarioExecutionIds, page); + return new PageImpl<>(scenarioExecutions.getContent(), page, scenarioExecutionRepository.count(specification)); } /** diff --git a/simulator-spring-boot/src/main/java/org/citrusframework/simulator/service/TestResultQueryService.java b/simulator-spring-boot/src/main/java/org/citrusframework/simulator/service/TestResultQueryService.java index 6ae43df87..af6816c7a 100644 --- a/simulator-spring-boot/src/main/java/org/citrusframework/simulator/service/TestResultQueryService.java +++ b/simulator-spring-boot/src/main/java/org/citrusframework/simulator/service/TestResultQueryService.java @@ -1,5 +1,5 @@ /* - * Copyright 2023 the original author or authors. + * Copyright 2023-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,37 +16,40 @@ package org.citrusframework.simulator.service; +import static org.citrusframework.simulator.service.CriteriaQueryUtils.newSelectIdBySpecificationQuery; + +import jakarta.persistence.EntityManager; import jakarta.persistence.criteria.JoinType; +import java.util.List; +import lombok.extern.slf4j.Slf4j; import org.citrusframework.simulator.model.TestParameter_; import org.citrusframework.simulator.model.TestResult; import org.citrusframework.simulator.model.TestResult_; import org.citrusframework.simulator.repository.TestResultRepository; import org.citrusframework.simulator.service.criteria.TestResultCriteria; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.domain.Specification; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.List; - /** * Service for executing complex queries for {@link TestResult} entities in the database. * The main input is a {@link TestResultCriteria} which gets converted to {@link Specification}, * in a way that all the filters must apply. * It returns a {@link List} of {@link TestResult} or a {@link Page} of {@link TestResult} which fulfills the criteria. */ +@Slf4j @Service @Transactional(readOnly = true) public class TestResultQueryService extends QueryService { - private static final Logger logger = LoggerFactory.getLogger(TestResultQueryService.class); - + private final EntityManager entityManager; private final TestResultRepository testResultRepository; - public TestResultQueryService(TestResultRepository testResultRepository) { + public TestResultQueryService(EntityManager entityManager, TestResultRepository testResultRepository) { + this.entityManager = entityManager; this.testResultRepository = testResultRepository; } @@ -59,8 +62,19 @@ public TestResultQueryService(TestResultRepository testResultRepository) { @Transactional(readOnly = true) public Page findByCriteria(TestResultCriteria criteria, Pageable page) { logger.debug("find by criteria : {}, page: {}", criteria, page); - final Specification specification = createSpecification(criteria); - return testResultRepository.findAll(specification, page); + + var specification = createSpecification(criteria); + var testResultIds = newSelectIdBySpecificationQuery( + TestResult.class, + TestResult_.id, + specification, + page, + entityManager + ) + .getResultList(); + + var testResults = testResultRepository.findAllWhereIdIn(testResultIds, page); + return new PageImpl<>(testResults.getContent(), page, testResultRepository.count(specification)); } /** diff --git a/simulator-spring-boot/src/test/java/org/citrusframework/simulator/service/MessageQueryServiceIT.java b/simulator-spring-boot/src/test/java/org/citrusframework/simulator/service/MessageQueryServiceIT.java new file mode 100644 index 000000000..3edf3f44c --- /dev/null +++ b/simulator-spring-boot/src/test/java/org/citrusframework/simulator/service/MessageQueryServiceIT.java @@ -0,0 +1,206 @@ +package org.citrusframework.simulator.service; + +import jakarta.persistence.EntityManager; +import org.citrusframework.simulator.IntegrationTest; +import org.citrusframework.simulator.model.Message; +import org.citrusframework.simulator.model.Message_; +import org.citrusframework.simulator.repository.MessageRepository; +import org.citrusframework.simulator.service.criteria.MessageCriteria; +import org.citrusframework.simulator.service.filter.LongFilter; +import org.citrusframework.simulator.web.rest.MessageResourceIT; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.parallel.Isolated; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort; + +import java.time.Instant; +import java.util.LinkedList; +import java.util.List; +import java.util.stream.Stream; + +import static java.time.temporal.ChronoUnit.MINUTES; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.params.provider.Arguments.arguments; +import static org.springframework.data.domain.Sort.Direction.ASC; +import static org.springframework.data.domain.Sort.Direction.DESC; + +@Isolated +@IntegrationTest +class MessageQueryServiceIT { + + @Autowired + private MessageRepository messageRepository; + + @Autowired + private EntityManager entityManager; + + @Autowired + private MessageQueryService fixture; + + private List messages; + + @BeforeEach + void beforeEachSetup() { + var now = Instant.now(); + + messages = new LinkedList<>(); + messages.add( + MessageResourceIT.createEntityBuilder(entityManager) + .citrusMessageId("4c7964f8-c1c7-492a-856a-48b10fec5363") + .createdDate(now.minus(1, MINUTES)) + .build()); + messages.add( + MessageResourceIT.createEntityBuilder(entityManager) + .citrusMessageId("30b418d2-c9e4-4be1-b6cf-5ab9ac9af6c3") + .createdDate(now) + .build()); + messages.add( + MessageResourceIT.createEntityBuilder(entityManager) + .citrusMessageId("4ff1c316-6ed3-4b5e-809b-4d76215346f1") + .createdDate(now.minus(1, MINUTES)) + .build()); + + messageRepository.saveAll(messages); + } + + @Nested + class FindByCriteria { + + @Test + void selectMessageIdLessThan() { + var messageCriteria = new MessageCriteria(); + messageCriteria.setMessageId((LongFilter) new LongFilter().setLessThan(messages.get(1).getMessageId())); + + assertThatMessageAtIndexSelectedByCriteria(messageCriteria, 0); + } + + @Test + void selectMessageIdLessThanOrEqualTo() { + var messageCriteria = new MessageCriteria(); + messageCriteria.setMessageId((LongFilter) new LongFilter().setLessThanOrEqual(messages.get(1).getMessageId())); + + Page messagePage = fixture.findByCriteria( + messageCriteria, + PageRequest.of(0, 2, Sort.by(ASC, Message_.MESSAGE_ID)) + ); + + assertThat(messagePage.getTotalPages()).isEqualTo(1); + assertThat(messagePage.getTotalElements()).isEqualTo(2L); + assertThat(messagePage.getContent()) + .hasSize(2) + .containsExactly( + messages.get(0), + messages.get(1)); + } + + @Test + void selectMessageIdGreaterThan() { + var messageCriteria = new MessageCriteria(); + messageCriteria.setMessageId((LongFilter) new LongFilter().setGreaterThan(messages.get(1).getMessageId())); + + assertThatMessageAtIndexSelectedByCriteria(messageCriteria, 2); + } + + static Stream testPagination() { + return Stream.of( + arguments(1, 3), + arguments(2, 2), + arguments(3, 1) + ); + } + + @MethodSource + @ParameterizedTest + void testPagination(int pageSize, int expectedTotalPages) { + Page messagePage = fixture.findByCriteria( + new MessageCriteria(), + PageRequest.of(0, pageSize, Sort.by(ASC, Message_.MESSAGE_ID)) + ); + + assertThat(messagePage.getTotalPages()).isEqualTo(expectedTotalPages); + assertThat(messagePage.getTotalElements()).isEqualTo(3L); + assertThat(messagePage.getContent()).hasSize(pageSize); + } + + static Stream testSinglePropertySort() { + return Stream.of( + arguments( + ASC, + new String[]{Message_.MESSAGE_ID}, + new int[]{0, 1, 2}), + arguments( + DESC, + new String[]{Message_.MESSAGE_ID}, + new int[]{2, 1, 0}), + arguments( + ASC, + new String[]{Message_.CITRUS_MESSAGE_ID}, + new int[]{1, 0, 2}), + arguments( + DESC, + new String[]{Message_.CITRUS_MESSAGE_ID}, + new int[]{2, 0, 1}) + ); + } + + @MethodSource + @ParameterizedTest + void testSinglePropertySort(Sort.Direction direction, String[] propertyNames, int[] indexOrder) { + testSort(direction, propertyNames, indexOrder); + } + + static Stream testMultiplePropertySort() { + return Stream.of( + arguments( + ASC, + new String[]{Message_.CREATED_DATE, Message_.MESSAGE_ID}, + new int[]{0, 2, 1}), + arguments( + DESC, + new String[]{Message_.CREATED_DATE, Message_.MESSAGE_ID}, + new int[]{1, 2, 0}) + ); + } + + @MethodSource + @ParameterizedTest + void testMultiplePropertySort(Sort.Direction direction, String[] propertyNames, int[] indexOrder) { + testSort(direction, propertyNames, indexOrder); + } + + private void testSort(Sort.Direction direction, String[] propertyNames, int[] indexOrder) { + Page messagePage = fixture.findByCriteria( + new MessageCriteria(), + PageRequest.of(0, 3, Sort.by(direction, propertyNames)) + ); + + assertThat(messagePage) + .hasSize(3) + .containsExactly( + messages.get(indexOrder[0]), + messages.get(indexOrder[1]), + messages.get(indexOrder[2])); + } + } + + @AfterEach + void afterEachTeardown() { + messageRepository.deleteAll(messages); + } + + private void assertThatMessageAtIndexSelectedByCriteria(MessageCriteria messageCriteria, int index) { + Page messagePage = fixture.findByCriteria(messageCriteria, PageRequest.of(0, 1, Sort.by(ASC, Message_.MESSAGE_ID))); + + assertThat(messagePage.getTotalPages()).isEqualTo(1); + assertThat(messagePage.getTotalElements()).isEqualTo(1L); + assertThat(messagePage.getContent()).hasSize(1).first().isEqualTo(messages.get(index)); + } +} diff --git a/simulator-spring-boot/src/test/java/org/citrusframework/simulator/service/ScenarioExecutionQueryServiceIT.java b/simulator-spring-boot/src/test/java/org/citrusframework/simulator/service/ScenarioExecutionQueryServiceIT.java new file mode 100644 index 000000000..8ea373bcf --- /dev/null +++ b/simulator-spring-boot/src/test/java/org/citrusframework/simulator/service/ScenarioExecutionQueryServiceIT.java @@ -0,0 +1,274 @@ +package org.citrusframework.simulator.service; + +import jakarta.persistence.EntityManager; +import org.citrusframework.simulator.IntegrationTest; +import org.citrusframework.simulator.model.Message; +import org.citrusframework.simulator.model.ScenarioAction; +import org.citrusframework.simulator.model.ScenarioExecution; +import org.citrusframework.simulator.model.ScenarioExecution_; +import org.citrusframework.simulator.model.ScenarioParameter; +import org.citrusframework.simulator.repository.ScenarioExecutionRepository; +import org.citrusframework.simulator.service.criteria.ScenarioExecutionCriteria; +import org.citrusframework.simulator.service.filter.LongFilter; +import org.citrusframework.simulator.web.rest.MessageResourceIT; +import org.citrusframework.simulator.web.rest.ScenarioActionResourceIT; +import org.citrusframework.simulator.web.rest.ScenarioExecutionResourceIT; +import org.citrusframework.simulator.web.rest.ScenarioParameterResourceIT; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.parallel.Isolated; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort; +import org.springframework.data.domain.Sort.Direction; + +import java.time.Instant; +import java.util.LinkedList; +import java.util.List; +import java.util.stream.Stream; + +import static java.time.temporal.ChronoUnit.MINUTES; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.params.provider.Arguments.arguments; +import static org.springframework.data.domain.Sort.Direction.ASC; +import static org.springframework.data.domain.Sort.Direction.DESC; + +@Isolated +@IntegrationTest +class ScenarioExecutionQueryServiceIT { + + @Autowired + private ScenarioExecutionRepository scenarioExecutionRepository; + + @Autowired + private EntityManager entityManager; + + @Autowired + private ScenarioExecutionQueryService fixture; + + private ScenarioAction scenarioAction; + private Message message; + private ScenarioParameter scenarioParameter; + + private List scenarioExecutions; + + @BeforeEach + void beforeEachSetup() { + var now = Instant.now(); + + scenarioAction = ScenarioActionResourceIT.createEntity(entityManager); + message = MessageResourceIT.createEntityBuilder(entityManager) + .citrusMessageId("e4d560c9-720f-4283-ac89-8f28b1d0f277") + .build(); + scenarioParameter = ScenarioParameterResourceIT.createEntityBuilder(entityManager) + .name("John") + .value("Snow") + .build(); + + scenarioExecutions = new LinkedList<>(); + scenarioExecutions.add( + ScenarioExecutionResourceIT.createEntityBuilder(entityManager) + .startDate(now.minus(2, MINUTES)) + .endDate(now.minus(1, MINUTES)) + .build() + .addScenarioAction(ScenarioActionResourceIT.createEntity(entityManager)) + .addScenarioMessage( + MessageResourceIT.createEntityBuilder(entityManager) + .citrusMessageId("6eda9f2b-3a7a-423f-b19c-329ed3dd5ecc") + .build()) + .addScenarioParameter(scenarioParameter)); + scenarioExecutions.add( + ScenarioExecutionResourceIT.createEntityBuilder(entityManager) + .startDate(now.minus(4, MINUTES)) + .endDate(now) + .build() + .addScenarioAction(ScenarioActionResourceIT.createEntity(entityManager)) + .addScenarioMessage(message) + .addScenarioParameter( + ScenarioParameterResourceIT.createEntityBuilder(entityManager) + .name("another") + .value("parameter") + .build())); + scenarioExecutions.add( + ScenarioExecutionResourceIT.createEntityBuilder(entityManager) + .startDate(now) + .endDate(now.minus(1, MINUTES)) + .build() + .addScenarioAction(scenarioAction) + .addScenarioMessage( + MessageResourceIT.createEntityBuilder(entityManager) + .citrusMessageId("66666a09-7099-461b-aebb-260e776cd07f") + .build()) + .addScenarioParameter( + ScenarioParameterResourceIT.createEntityBuilder(entityManager) + .name("foo") + .value("bar") + .build())); + + scenarioExecutionRepository.saveAll(scenarioExecutions); + } + + @Nested + class FindByCriteria { + + @Test + void selectExecutionIdLessThan() { + var scenarioExecutionCriteria = new ScenarioExecutionCriteria(); + scenarioExecutionCriteria.setExecutionId((LongFilter) new LongFilter().setLessThan(scenarioExecutions.get(1).getExecutionId())); + + assertThatScenarioExecutionAtIndexSelectedByCriteria(scenarioExecutionCriteria, 0); + } + + @Test + void selectExecutionIdLessThanOrEqualTo() { + var scenarioExecutionCriteria = new ScenarioExecutionCriteria(); + scenarioExecutionCriteria.setExecutionId((LongFilter) new LongFilter().setLessThanOrEqual(scenarioExecutions.get(1).getExecutionId())); + + Page scenarioExecutionPage = fixture.findByCriteria( + scenarioExecutionCriteria, + PageRequest.of(0, 2, Sort.by(ASC, ScenarioExecution_.EXECUTION_ID)) + ); + + assertThat(scenarioExecutionPage.getTotalPages()).isEqualTo(1); + assertThat(scenarioExecutionPage.getTotalElements()).isEqualTo(2L); + assertThat(scenarioExecutionPage.getContent()) + .hasSize(2) + .containsExactly( + scenarioExecutions.get(0), + scenarioExecutions.get(1)); + } + + @Test + void selectExecutionIdGreaterThan() { + var scenarioExecutionCriteria = new ScenarioExecutionCriteria(); + scenarioExecutionCriteria.setExecutionId((LongFilter) new LongFilter().setGreaterThan(scenarioExecutions.get(1).getExecutionId())); + + assertThatScenarioExecutionAtIndexSelectedByCriteria(scenarioExecutionCriteria, 2); + } + + @Test + void selectWithJoinToScenarioActions() { + var scenarioExecutionCriteria = new ScenarioExecutionCriteria(); + scenarioExecutionCriteria.setScenarioActionsId((LongFilter) new LongFilter().setEquals(scenarioAction.getActionId())); + + assertThatScenarioExecutionAtIndexSelectedByCriteria(scenarioExecutionCriteria, 2); + } + + @Test + void selectWithJoinToMessages() { + var scenarioExecutionCriteria = new ScenarioExecutionCriteria(); + scenarioExecutionCriteria.setScenarioMessagesId((LongFilter) new LongFilter().setEquals(message.getMessageId())); + + assertThatScenarioExecutionAtIndexSelectedByCriteria(scenarioExecutionCriteria, 1); + } + + @Test + void selectWithJoinToScenarioParameters() { + var scenarioExecutionCriteria = new ScenarioExecutionCriteria(); + scenarioExecutionCriteria.setScenarioParametersId((LongFilter) new LongFilter().setEquals(scenarioParameter.getParameterId())); + + assertThatScenarioExecutionAtIndexSelectedByCriteria(scenarioExecutionCriteria, 0); + } + + static Stream testPagination() { + return Stream.of( + arguments(1, 3), + arguments(2, 2), + arguments(3, 1) + ); + } + + @MethodSource + @ParameterizedTest + void testPagination(int pageSize, int expectedTotalPages) { + Page scenarioExecutionPage = fixture.findByCriteria( + new ScenarioExecutionCriteria(), + PageRequest.of(0, pageSize, Sort.by(ASC, ScenarioExecution_.EXECUTION_ID)) + ); + + assertThat(scenarioExecutionPage.getTotalPages()).isEqualTo(expectedTotalPages); + assertThat(scenarioExecutionPage.getTotalElements()).isEqualTo(3L); + assertThat(scenarioExecutionPage.getContent()).hasSize(pageSize); + } + + static Stream testSinglePropertySort() { + return Stream.of( + arguments( + ASC, + new String[]{ScenarioExecution_.EXECUTION_ID}, + new int[]{0, 1, 2}), + arguments( + DESC, + new String[]{ScenarioExecution_.EXECUTION_ID}, + new int[]{2, 1, 0}), + arguments( + ASC, + new String[]{ScenarioExecution_.START_DATE}, + new int[]{1, 0, 2}), + arguments( + DESC, + new String[]{ScenarioExecution_.START_DATE}, + new int[]{2, 0, 1}) + ); + } + + @MethodSource + @ParameterizedTest + void testSinglePropertySort(Direction direction, String[] propertyNames, int[] indexOrder) { + testSort(direction, propertyNames, indexOrder); + } + + static Stream testMultiplePropertySort() { + return Stream.of( + arguments( + ASC, + new String[]{ScenarioExecution_.END_DATE, ScenarioExecution_.EXECUTION_ID}, + new int[]{0, 2, 1}), + arguments( + DESC, + new String[]{ScenarioExecution_.END_DATE, ScenarioExecution_.EXECUTION_ID}, + new int[]{1, 2, 0}) + ); + } + + @MethodSource + @ParameterizedTest + void testMultiplePropertySort(Direction direction, String[] propertyNames, int[] indexOrder) { + testSort(direction, propertyNames, indexOrder); + } + + private void testSort(Direction direction, String[] propertyNames, int[] indexOrder) { + Page scenarioExecutionPage = fixture.findByCriteria( + new ScenarioExecutionCriteria(), + PageRequest.of(0, 3, Sort.by(direction, propertyNames)) + ); + + assertThat(scenarioExecutionPage) + .hasSize(3) + .containsExactly( + scenarioExecutions.get(indexOrder[0]), + scenarioExecutions.get(indexOrder[1]), + scenarioExecutions.get(indexOrder[2]) + ); + } + } + + @AfterEach + void afterEachTeardown() { + scenarioExecutionRepository.deleteAll(scenarioExecutions); + } + + private void assertThatScenarioExecutionAtIndexSelectedByCriteria(ScenarioExecutionCriteria scenarioExecutionCriteria, int index) { + Page scenarioExecutionPage = fixture.findByCriteria(scenarioExecutionCriteria, PageRequest.of(0, 1, Sort.by(ASC, ScenarioExecution_.EXECUTION_ID))); + + assertThat(scenarioExecutionPage.getTotalPages()).isEqualTo(1); + assertThat(scenarioExecutionPage.getTotalElements()).isEqualTo(1L); + assertThat(scenarioExecutionPage.getContent()).hasSize(1).first().isEqualTo(scenarioExecutions.get(index)); + } +} diff --git a/simulator-spring-boot/src/test/java/org/citrusframework/simulator/service/TestResultQueryServiceIT.java b/simulator-spring-boot/src/test/java/org/citrusframework/simulator/service/TestResultQueryServiceIT.java new file mode 100644 index 000000000..9cdb87feb --- /dev/null +++ b/simulator-spring-boot/src/test/java/org/citrusframework/simulator/service/TestResultQueryServiceIT.java @@ -0,0 +1,238 @@ +package org.citrusframework.simulator.service; + +import jakarta.persistence.EntityManager; +import org.citrusframework.simulator.IntegrationTest; +import org.citrusframework.simulator.model.TestParameter; +import org.citrusframework.simulator.model.TestResult; +import org.citrusframework.simulator.model.TestResult_; +import org.citrusframework.simulator.repository.TestResultRepository; +import org.citrusframework.simulator.service.criteria.TestResultCriteria; +import org.citrusframework.simulator.service.filter.LongFilter; +import org.citrusframework.simulator.service.filter.StringFilter; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.parallel.Isolated; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort; +import org.springframework.transaction.annotation.Transactional; + +import java.util.LinkedList; +import java.util.List; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.params.provider.Arguments.arguments; +import static org.springframework.data.domain.Sort.Direction.ASC; +import static org.springframework.data.domain.Sort.Direction.DESC; + +@Isolated +@Transactional +@IntegrationTest +class TestResultQueryServiceIT { + + @Autowired + private TestResultRepository testResultRepository; + + @Autowired + private EntityManager entityManager; + + @Autowired + private TestResultQueryService fixture; + + private List testResults; + + @BeforeEach + void beforeEachSetup() { + testResults = new LinkedList<>(); + testResults.add( + TestResult.builder() + .testName("B") + .className(getClass().getSimpleName()) + .errorMessage("an error has occurred :o") + .build()); + testResults.add( + TestResult.builder() + .testName("A") + .className(getClass().getSimpleName()) + .errorMessage("z-index is something in web development, isn't it?") + .build()); + testResults.add( + TestResult.builder() + .testName("C") + .className(getClass().getSimpleName()) + .errorMessage("an error has occurred :o") + .build()); + + testResultRepository.saveAll(testResults); + + var testParameter1 = TestParameter.builder() + .key("key") + .value("value") + .build(); + testResults.get(0).addTestParameter(testParameter1); + entityManager.persist(testParameter1); + + var testParameter2 = TestParameter.builder() + .key("the chosen one") + .value("is?") + .build(); + testResults.get(1).addTestParameter(testParameter2); + entityManager.persist(testParameter2); + + var testParameter3 = TestParameter.builder() + .key("foo") + .value("bar") + .build(); + testResults.get(2).addTestParameter(testParameter3); + entityManager.persist(testParameter3); + } + + @Nested + class FindByCriteria { + + @Test + void selectTestResultIdLessThan() { + var testResultCriteria = new TestResultCriteria(); + testResultCriteria.setId((LongFilter) new LongFilter().setLessThan(testResults.get(1).getId())); + + assertThatTestResultAtIndexSelectedByCriteria(testResultCriteria, 0); + } + + @Test + void selectMessageIdLessThanOrEqualTo() { + var testResultCriteria = new TestResultCriteria(); + testResultCriteria.setId((LongFilter) new LongFilter().setLessThanOrEqual(testResults.get(1).getId())); + + Page testResultPage = fixture.findByCriteria( + testResultCriteria, + PageRequest.of(0, 2, Sort.by(ASC, TestResult_.ID)) + ); + + assertThat(testResultPage.getTotalPages()).isEqualTo(1); + assertThat(testResultPage.getTotalElements()).isEqualTo(2L); + assertThat(testResultPage.getContent()) + .hasSize(2) + .containsExactly( + testResults.get(0), + testResults.get(1)); + } + + @Test + void selectTestResultIdGreaterThan() { + var testResultCriteria = new TestResultCriteria(); + testResultCriteria.setId((LongFilter) new LongFilter().setGreaterThan(testResults.get(1).getId())); + + assertThatTestResultAtIndexSelectedByCriteria(testResultCriteria, 2); + } + + @Test + void selectWithJoinToTestParameters() { + var testResultCriteria = new TestResultCriteria(); + testResultCriteria.setTestParameterKey(new StringFilter().setContains("chosen")); + + assertThatTestResultAtIndexSelectedByCriteria(testResultCriteria, 1); + } + + static Stream testPagination() { + return Stream.of( + arguments(1, 3), + arguments(2, 2), + arguments(3, 1) + ); + } + + @MethodSource + @ParameterizedTest + void testPagination(int pageSize, int expectedTotalPages) { + Page testResultPage = fixture.findByCriteria( + new TestResultCriteria(), + PageRequest.of(0, pageSize, Sort.by(ASC, TestResult_.ID)) + ); + + assertThat(testResultPage.getTotalPages()).isEqualTo(expectedTotalPages); + assertThat(testResultPage.getTotalElements()).isEqualTo(3L); + assertThat(testResultPage.getContent()).hasSize(pageSize); + } + + static Stream testSinglePropertySort() { + return Stream.of( + arguments( + ASC, + new String[]{TestResult_.ID}, + new int[]{0, 1, 2}), + arguments( + DESC, + new String[]{TestResult_.ID}, + new int[]{2, 1, 0}), + arguments( + ASC, + new String[]{TestResult_.TEST_NAME}, + new int[]{1, 0, 2}), + arguments( + DESC, + new String[]{TestResult_.TEST_NAME}, + new int[]{2, 0, 1}) + ); + } + + @MethodSource + @ParameterizedTest + void testSinglePropertySort(Sort.Direction direction, String[] propertyNames, int[] indexOrder) { + testSort(direction, propertyNames, indexOrder); + } + + static Stream testMultiplePropertySort() { + return Stream.of( + arguments( + ASC, + new String[]{TestResult_.ERROR_MESSAGE, TestResult_.ID}, + new int[]{0, 2, 1}), + arguments( + DESC, + new String[]{TestResult_.ERROR_MESSAGE, TestResult_.ID}, + new int[]{1, 2, 0}) + ); + } + + @MethodSource + @ParameterizedTest + void testMultiplePropertySort(Sort.Direction direction, String[] propertyNames, int[] indexOrder) { + testSort(direction, propertyNames, indexOrder); + } + + private void testSort(Sort.Direction direction, String[] propertyNames, int[] indexOrder) { + Page testResultPage = fixture.findByCriteria( + new TestResultCriteria(), + PageRequest.of(0, 3, Sort.by(direction, propertyNames)) + ); + + assertThat(testResultPage) + .hasSize(3) + .containsExactly( + testResults.get(indexOrder[0]), + testResults.get(indexOrder[1]), + testResults.get(indexOrder[2]) + ); + } + } + + private void assertThatTestResultAtIndexSelectedByCriteria(TestResultCriteria testResultCriteria, int index) { + Page testResultPage = fixture.findByCriteria(testResultCriteria, PageRequest.of(0, 1, Sort.by(ASC, TestResult_.ID))); + + assertThat(testResultPage.getTotalPages()).isEqualTo(1); + assertThat(testResultPage.getTotalElements()).isEqualTo(1L); + assertThat(testResultPage.getContent()).hasSize(1).first().isEqualTo(testResults.get(index)); + } + + @AfterEach + void afterEachTeardown() { + testResultRepository.deleteAll(testResults); + } +} diff --git a/simulator-spring-boot/src/test/java/org/citrusframework/simulator/web/rest/MessageResourceIT.java b/simulator-spring-boot/src/test/java/org/citrusframework/simulator/web/rest/MessageResourceIT.java index 8a835a0b4..35a2fb97d 100644 --- a/simulator-spring-boot/src/test/java/org/citrusframework/simulator/web/rest/MessageResourceIT.java +++ b/simulator-spring-boot/src/test/java/org/citrusframework/simulator/web/rest/MessageResourceIT.java @@ -3,6 +3,7 @@ import jakarta.persistence.EntityManager; import org.citrusframework.simulator.IntegrationTest; import org.citrusframework.simulator.model.Message; +import org.citrusframework.simulator.model.Message.MessageBuilder; import org.citrusframework.simulator.model.MessageHeader; import org.citrusframework.simulator.model.ScenarioExecution; import org.citrusframework.simulator.repository.MessageRepository; @@ -64,6 +65,15 @@ public class MessageResourceIT { private Message message; + public static MessageBuilder createEntityBuilder(EntityManager entityManager) { + return Message.builder() + .direction(DEFAULT_DIRECTION) + .payload(DEFAULT_PAYLOAD) + .citrusMessageId(DEFAULT_CITRUS_MESSAGE_ID) + .createdDate(DEFAULT_CREATED_DATE) + .lastModifiedDate(DEFAULT_LAST_MODIFIED_DATE); + } + /** * Create an entity for this test. *

@@ -71,12 +81,7 @@ public class MessageResourceIT { * if they test an entity which requires the current entity. */ public static Message createEntity(EntityManager entityManager) { - return Message.builder() - .direction(DEFAULT_DIRECTION) - .payload(DEFAULT_PAYLOAD) - .citrusMessageId(DEFAULT_CITRUS_MESSAGE_ID) - .createdDate(DEFAULT_CREATED_DATE) - .lastModifiedDate(DEFAULT_LAST_MODIFIED_DATE) + return createEntityBuilder(entityManager) .build(); } diff --git a/simulator-spring-boot/src/test/java/org/citrusframework/simulator/web/rest/ScenarioExecutionResourceIT.java b/simulator-spring-boot/src/test/java/org/citrusframework/simulator/web/rest/ScenarioExecutionResourceIT.java index c9b24ecee..ae3ab93c9 100644 --- a/simulator-spring-boot/src/test/java/org/citrusframework/simulator/web/rest/ScenarioExecutionResourceIT.java +++ b/simulator-spring-boot/src/test/java/org/citrusframework/simulator/web/rest/ScenarioExecutionResourceIT.java @@ -5,6 +5,7 @@ import org.citrusframework.simulator.model.Message; import org.citrusframework.simulator.model.ScenarioAction; import org.citrusframework.simulator.model.ScenarioExecution; +import org.citrusframework.simulator.model.ScenarioExecution.ScenarioExecutionBuilder; import org.citrusframework.simulator.model.ScenarioParameter; import org.citrusframework.simulator.repository.ScenarioExecutionRepository; import org.junit.jupiter.api.BeforeEach; @@ -62,6 +63,15 @@ public class ScenarioExecutionResourceIT { private ScenarioExecution scenarioExecution; + public static ScenarioExecutionBuilder createEntityBuilder(EntityManager entityManager) { + return ScenarioExecution.builder() + .startDate(DEFAULT_START_DATE) + .endDate(DEFAULT_END_DATE) + .scenarioName(DEFAULT_SCENARIO_NAME) + .status(DEFAULT_STATUS) + .errorMessage(DEFAULT_ERROR_MESSAGE); + } + /** * Create an entity for this test. *

@@ -69,14 +79,8 @@ public class ScenarioExecutionResourceIT { * if they test an entity which requires the current entity. */ public static ScenarioExecution createEntity(EntityManager entityManager) { - ScenarioExecution scenarioExecution = ScenarioExecution.builder() - .startDate(DEFAULT_START_DATE) - .endDate(DEFAULT_END_DATE) - .scenarioName(DEFAULT_SCENARIO_NAME) - .status(DEFAULT_STATUS) - .errorMessage(DEFAULT_ERROR_MESSAGE) + return createEntityBuilder(entityManager) .build(); - return scenarioExecution; } /** @@ -86,14 +90,13 @@ public static ScenarioExecution createEntity(EntityManager entityManager) { * if they test an entity which requires the current entity. */ public static ScenarioExecution createUpdatedEntity(EntityManager entityManager) { - ScenarioExecution scenarioExecution = ScenarioExecution.builder() + return ScenarioExecution.builder() .startDate(UPDATED_START_DATE) .endDate(UPDATED_END_DATE) .scenarioName(UPDATED_SCENARIO_NAME) .status(UPDATED_STATUS) .errorMessage(UPDATED_ERROR_MESSAGE) .build(); - return scenarioExecution; } @BeforeEach diff --git a/simulator-spring-boot/src/test/java/org/citrusframework/simulator/web/rest/ScenarioParameterResourceIT.java b/simulator-spring-boot/src/test/java/org/citrusframework/simulator/web/rest/ScenarioParameterResourceIT.java index e0b02ca74..f1f212ea7 100644 --- a/simulator-spring-boot/src/test/java/org/citrusframework/simulator/web/rest/ScenarioParameterResourceIT.java +++ b/simulator-spring-boot/src/test/java/org/citrusframework/simulator/web/rest/ScenarioParameterResourceIT.java @@ -63,6 +63,15 @@ public class ScenarioParameterResourceIT { private ScenarioParameter scenarioParameter; + public static ScenarioParameter.ScenarioParameterBuilder createEntityBuilder(EntityManager entityManager) { + return ScenarioParameter.builder() + .name(DEFAULT_NAME) + .controlType(DEFAULT_CONTROL_TYPE) + .value(DEFAULT_VALUE) + .createdDate(DEFAULT_CREATED_DATE) + .lastModifiedDate(DEFAULT_LAST_MODIFIED_DATE); + } + /** * Create an entity for this test. *

@@ -70,12 +79,7 @@ public class ScenarioParameterResourceIT { * if they test an entity which requires the current entity. */ public static ScenarioParameter createEntity(EntityManager entityManager) { - return ScenarioParameter.builder() - .name(DEFAULT_NAME) - .controlType(DEFAULT_CONTROL_TYPE) - .value(DEFAULT_VALUE) - .createdDate(DEFAULT_CREATED_DATE) - .lastModifiedDate(DEFAULT_LAST_MODIFIED_DATE) + return createEntityBuilder(entityManager) .build(); }