From bcb593c789642fc951dad026c600172f8a604d59 Mon Sep 17 00:00:00 2001 From: bbortt Date: Wed, 15 Jan 2025 18:01:11 +0100 Subject: [PATCH] fix(simulator): scenario execution performance improved performance of `/api/scenario-executions` endpoint. instead of fetching all relationships and then trimming the result, relationships are now only conditionally being fetched. --- .../src/main/asciidoc/rest-api.adoc | 16 +- .../ScenarioExecutionRepository.java | 4 - .../ScenarioExecutionQueryService.java | 84 +++++++++- .../web/rest/ScenarioExecutionResource.java | 37 ++--- .../ScenarioExecutionQueryServiceIT.java | 149 +++++++++++++++-- .../web/rest/MessageHeaderResourceIT.java | 1 + .../web/rest/ScenarioExecutionResourceIT.java | 152 ++++-------------- .../rest/ScenarioExecutionResourceTest.java | 100 +++++++----- 8 files changed, 342 insertions(+), 201 deletions(-) diff --git a/simulator-docs/src/main/asciidoc/rest-api.adoc b/simulator-docs/src/main/asciidoc/rest-api.adoc index ffc6ae382..39bb33d1f 100644 --- a/simulator-docs/src/main/asciidoc/rest-api.adoc +++ b/simulator-docs/src/main/asciidoc/rest-api.adoc @@ -28,7 +28,21 @@ The endpoint `/api/test-results` additionally supports the `DELETE` request that === Receive SINGLE Test-Parameter A `TestParameter` is uniquely identified by a composite key, consisting of the `TestResult` ID and the `TestParameter` key. -To retrieve a single `TestParameter`, use the `GET /{testResultId}/{key}` endpoint. +To retrieve a single `TestParameter`, use the `GET /api/test-parameters/{testResultId}/{key}` endpoint. all recorded Test Results and Executions. + +[[receive-scenario-execution-details]] +=== Receive Scenario Execution with Details + +The `ScenarioExecution` is also unique in regard to the amount of details that _could_ be extracted from it. +However, more information (almost) always comes at the cost of performance. +Thus, the `/api/scenario-executions` endpoint offers four unique boolean query parameters: + +* `includeActions`: When `true`, additionally fetches related `ScenarioAction` +* `includeMessages`: When `true`, additionally fetches related `Message` (without `MessageHeader`) +* `includeMessageHeaders`: When `true`, additionally fetches related `Message` and `MessageHeaders` +* `includeParameters`: When `true`, additionally fetches related `ScenarioParameter` + +They are all being set to `false` by default. [[scenario-resource]] === Scenario Resource 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 71b107787..c9d618969 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 @@ -41,8 +41,4 @@ public interface ScenarioExecutionRepository extends JpaRepository findOneByExecutionId(@Param("executionId") Long executionId); - - @Query("FROM ScenarioExecution WHERE executionId IN :scenarioExecutionIds") - @EntityGraph(attributePaths = {"testResult", "scenarioParameters", "scenarioActions", "scenarioMessages", "scenarioMessages.headers"}) - Page findAllWhereExecutionIdIn(@Param("scenarioExecutionIds") List scenarioExecutionIds, Pageable pageable); } 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 c87f861e6..afb0416fd 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 @@ -16,6 +16,7 @@ package org.citrusframework.simulator.service; +import com.google.common.annotations.VisibleForTesting; import jakarta.persistence.EntityManager; import jakarta.persistence.criteria.JoinType; import jakarta.persistence.criteria.Path; @@ -59,8 +60,8 @@ import static org.citrusframework.simulator.service.CriteriaQueryUtils.newSelectIdBySpecificationQuery; import static org.citrusframework.simulator.service.ScenarioExecutionQueryService.MessageHeaderFilter.fromFilterPattern; import static org.citrusframework.simulator.service.ScenarioExecutionQueryService.Operator.parseOperator; +import static org.citrusframework.simulator.service.ScenarioExecutionQueryService.ResultDetailsConfiguration.withAllDetails; import static org.citrusframework.util.StringUtils.isEmpty; -import static org.springframework.data.domain.Pageable.unpaged; /** * Service for executing complex queries for {@link ScenarioExecution} entities in the database. @@ -84,10 +85,51 @@ public ScenarioExecutionQueryService(EntityManager entityManager, ScenarioExecut this.scenarioExecutionRepository = scenarioExecutionRepository; } + @VisibleForTesting static boolean isValidFilterPattern(String filterPattern) { return HEADER_FILTER_PATTERN.matcher(filterPattern).matches(); } + private static Specification withResultDetailsConfiguration(ResultDetailsConfiguration config) { + return (root, query, cb) -> { + assert query != null; + + // Prevent duplicate joins in count queries + if (query.getResultType() == Long.class || query.getResultType() == long.class) { + return null; + } + + root.fetch(ScenarioExecution_.testResult, JoinType.LEFT); + + if (config.includeParameters()) { + root.fetch(ScenarioExecution_.scenarioParameters, JoinType.LEFT); + } + + if (config.includeActions()) { + root.fetch(ScenarioExecution_.scenarioActions, JoinType.LEFT); + } + + if (config.includeMessages() || config.includeMessageHeaders()) { + var messagesJoin = root.fetch(ScenarioExecution_.scenarioMessages, JoinType.LEFT); + + if (config.includeMessageHeaders()) { + messagesJoin.fetch(Message_.headers, JoinType.LEFT); + } + } + + // Return no additional where clause + return null; + }; + } + + private static Specification withIds(List executionIds) { + return (root, query, builder) -> { + var in = builder.in(root.get(ScenarioExecution_.executionId)); + executionIds.forEach(in::value); + return in; + }; + } + /** * Return a {@link List} of {@link ScenarioExecution} which matches the criteria from the database. * @@ -110,6 +152,19 @@ public List findByCriteria(ScenarioExecutionCriteria criteria */ @Transactional(readOnly = true) public Page findByCriteria(ScenarioExecutionCriteria criteria, Pageable page) { + return findByCriteria(criteria, page, withAllDetails()); + } + + /** + * Return a {@link Page} of {@link ScenarioExecution} which matches the criteria from the database. + * + * @param criteria The object which holds all the filters, which the entities should match. + * @param page The page, which should be returned. + * @param resultDetailsConfiguration Fetch-configuration of relationships + * @return the matching entities. + */ + @Transactional(readOnly = true) + public Page findByCriteria(ScenarioExecutionCriteria criteria, Pageable page, ResultDetailsConfiguration resultDetailsConfiguration) { logger.debug("find by criteria : {}, page: {}", criteria, page); var specification = createSpecification(criteria); @@ -122,11 +177,20 @@ public Page findByCriteria(ScenarioExecutionCriteria criteria ) .getResultList(); - var scenarioExecutions = scenarioExecutionRepository.findAllWhereExecutionIdIn(scenarioExecutionIds, unpaged(page.getSort())); + if (scenarioExecutionIds.isEmpty()) { + return Page.empty(page); + } + + var fetchSpec = withIds(scenarioExecutionIds) + .and(withResultDetailsConfiguration(resultDetailsConfiguration)); + + var scenarioExecutions = scenarioExecutionRepository.findAll(fetchSpec, page.getSort()); + return new PageImpl<>( - scenarioExecutions.getContent(), + scenarioExecutions, page, - scenarioExecutionRepository.count(specification)); + scenarioExecutionRepository.count(specification) + ); } /** @@ -343,4 +407,16 @@ public InvalidPatternException(String filterPattern) { super(format("The header filter pattern '%s' does not comply with the regex '%s'!", filterPattern, HEADER_FILTER_PATTERN.pattern())); } } + + public record ResultDetailsConfiguration( + boolean includeActions, + boolean includeMessages, + boolean includeMessageHeaders, + boolean includeParameters + ) { + + static ResultDetailsConfiguration withAllDetails() { + return new ResultDetailsConfiguration(true, true, true, true); + } + } } diff --git a/simulator-spring-boot/src/main/java/org/citrusframework/simulator/web/rest/ScenarioExecutionResource.java b/simulator-spring-boot/src/main/java/org/citrusframework/simulator/web/rest/ScenarioExecutionResource.java index ce157b72c..7d2bdf57b 100644 --- a/simulator-spring-boot/src/main/java/org/citrusframework/simulator/web/rest/ScenarioExecutionResource.java +++ b/simulator-spring-boot/src/main/java/org/citrusframework/simulator/web/rest/ScenarioExecutionResource.java @@ -18,6 +18,7 @@ import org.citrusframework.simulator.model.ScenarioExecution; import org.citrusframework.simulator.service.ScenarioExecutionQueryService; +import org.citrusframework.simulator.service.ScenarioExecutionQueryService.ResultDetailsConfiguration; import org.citrusframework.simulator.service.ScenarioExecutionService; import org.citrusframework.simulator.service.criteria.ScenarioExecutionCriteria; import org.citrusframework.simulator.web.rest.dto.ScenarioExecutionDTO; @@ -40,7 +41,6 @@ import java.util.List; import java.util.Optional; -import static java.lang.Boolean.FALSE; import static org.citrusframework.simulator.web.util.PaginationUtil.generatePaginationHttpHeaders; /** @@ -77,21 +77,27 @@ public ScenarioExecutionResource( @GetMapping("/scenario-executions") public ResponseEntity> getAllScenarioExecutions( ScenarioExecutionCriteria criteria, - @RequestParam(name = "includeActions", required = false, defaultValue = "false") Boolean includeActions, - @RequestParam(name = "includeMessages", required = false, defaultValue = "false") Boolean includeMessages, - @RequestParam(name = "includeParameters", required = false, defaultValue = "false") Boolean includeParameters, + @RequestParam(name = "includeActions", required = false, defaultValue = "false") boolean includeActions, + @RequestParam(name = "includeMessages", required = false, defaultValue = "false") boolean includeMessages, + @RequestParam(name = "includeMessageHeaders", required = false, defaultValue = "false") boolean includeMessageHeaders, + @RequestParam(name = "includeParameters", required = false, defaultValue = "false") boolean includeParameters, @ParameterObject Pageable pageable ) { logger.debug("REST request to get ScenarioExecutions by criteria: {}", criteria); - Page page = scenarioExecutionQueryService.findByCriteria(criteria, pageable); + Page page = scenarioExecutionQueryService.findByCriteria( + criteria, + pageable, + new ResultDetailsConfiguration(includeActions, includeMessages, includeMessageHeaders, includeParameters) + ); HttpHeaders headers = generatePaginationHttpHeaders(ServletUriComponentsBuilder.fromCurrentRequest(), page); return ResponseEntity.ok() .headers(headers) - .body(page.getContent().stream() - .map(scenarioExecution -> stripPageContents(scenarioExecution, includeActions, includeMessages, includeParameters)) - .map(scenarioExecutionMapper::toDto) - .toList()); + .body( + page.getContent().stream() + .map(scenarioExecutionMapper::toDto) + .toList() + ); } /** @@ -118,17 +124,4 @@ public ResponseEntity getScenarioExecution(@PathVariable(" Optional scenarioExecution = scenarioExecutionService.findOne(id); return ResponseUtil.wrapOrNotFound(scenarioExecution.map(scenarioExecutionMapper::toDto)); } - - private ScenarioExecution stripPageContents(ScenarioExecution scenarioExecution, Boolean includeActions, Boolean includeMessages, Boolean includeParameters) { - if (FALSE.equals(includeActions)) { - scenarioExecution.getScenarioActions().clear(); - } - if (FALSE.equals(includeMessages)) { - scenarioExecution.getScenarioMessages().clear(); - } - if (FALSE.equals(includeParameters)) { - scenarioExecution.getScenarioParameters().clear(); - } - return scenarioExecution; - } } 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 index f8c2429a8..7d185ddd1 100644 --- 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 @@ -24,7 +24,6 @@ import org.citrusframework.simulator.model.ScenarioExecution; import org.citrusframework.simulator.model.ScenarioExecution_; import org.citrusframework.simulator.model.ScenarioParameter; -import org.citrusframework.simulator.model.TestResult_; import org.citrusframework.simulator.repository.ScenarioExecutionRepository; import org.citrusframework.simulator.service.criteria.ScenarioExecutionCriteria; import org.citrusframework.simulator.service.filter.IntegerFilter; @@ -35,6 +34,8 @@ import org.citrusframework.simulator.web.rest.ScenarioExecutionResourceIT; import org.citrusframework.simulator.web.rest.ScenarioParameterResourceIT; import org.citrusframework.simulator.web.rest.TestResultResourceIT; +import org.hibernate.LazyInitializationException; +import org.hibernate.collection.spi.PersistentSet; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; @@ -52,12 +53,16 @@ import java.time.Instant; import java.util.LinkedList; import java.util.List; +import java.util.function.Consumer; import java.util.stream.Stream; import static java.time.temporal.ChronoUnit.MINUTES; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.assertj.core.api.InstanceOfAssertFactories.type; import static org.citrusframework.simulator.model.TestResult.Status.FAILURE; import static org.junit.jupiter.params.provider.Arguments.arguments; +import static org.springframework.data.domain.Pageable.unpaged; import static org.springframework.data.domain.Sort.Direction.ASC; import static org.springframework.data.domain.Sort.Direction.DESC; @@ -180,6 +185,38 @@ void beforeEachSetup() { @Nested class FindByCriteria { + @Test + void selectAll() { + var scenarioExecutionCriteria = new ScenarioExecutionCriteria(); + Page scenarioExecutionPage = fixture.findByCriteria(scenarioExecutionCriteria, unpaged()); + + assertThat(scenarioExecutionPage) + .asInstanceOf(type(Page.class)) + .satisfies( + p -> assertThat(p.getTotalPages()).isEqualTo(1), + p -> assertThat(p.getTotalElements()).isEqualTo(3), + p -> assertThat(p.getContent()).hasSize(3), + p -> assertThat(p.getContent()) + .allSatisfy( + c -> assertThat(c) + .asInstanceOf(type(ScenarioExecution.class)) + .satisfies( + s -> assertThat(s.getTestResult().getStatus()).isNotNull(), + s -> assertThat(s.getScenarioParameters()).hasSize(1), + s -> assertThat(s.getScenarioActions()).hasSize(1), + s -> assertThat(s.getScenarioMessages()) + .hasSize(1) + .first() + .asInstanceOf(type(Message.class)) + .extracting(Message::getHeaders) + .asInstanceOf(type(PersistentSet.class)) + .extracting(PersistentSet::isEmpty) + .isEqualTo(false) + ) + ) + ); + } + @Test void selectExecutionIdLessThan() { var scenarioExecutionCriteria = new ScenarioExecutionCriteria(); @@ -216,7 +253,7 @@ void selectExecutionIdGreaterThan() { } @Test - void selectWithJoinToScenarioActions() { + void selectWithSelectiveJoinScenarioActions() { var scenarioExecutionCriteria = new ScenarioExecutionCriteria(); scenarioExecutionCriteria.setScenarioActionsId((LongFilter) new LongFilter().setEquals(scenarioAction.getActionId())); @@ -224,7 +261,7 @@ void selectWithJoinToScenarioActions() { } @Test - void selectWithJoinToMessages() { + void selectWithSelectiveJoinMessages() { var scenarioExecutionCriteria = new ScenarioExecutionCriteria(); scenarioExecutionCriteria.setScenarioMessagesId((LongFilter) new LongFilter().setEquals(message.getMessageId())); @@ -232,7 +269,7 @@ void selectWithJoinToMessages() { } @Test - void selectWithJoinToMessagesPayload() { + void selectWithSelectiveJoinMessagesPayload() { var scenarioExecutionCriteria = new ScenarioExecutionCriteria(); scenarioExecutionCriteria.setScenarioMessagesPayload((StringFilter) new StringFilter().setEquals(message.getPayload())); @@ -240,7 +277,7 @@ void selectWithJoinToMessagesPayload() { } @Test - void selectWithJoinToScenarioParameters() { + void selectWithSelectiveJoinScenarioParameters() { var scenarioExecutionCriteria = new ScenarioExecutionCriteria(); scenarioExecutionCriteria.setScenarioParametersId((LongFilter) new LongFilter().setEquals(scenarioParameter.getParameterId())); @@ -248,14 +285,14 @@ void selectWithJoinToScenarioParameters() { } @Test - void selectWithJoinToTestResult() { + void selectWithSelectiveJoinTestResult() { var scenarioExecutionCriteria = new ScenarioExecutionCriteria(); scenarioExecutionCriteria.setStatus((IntegerFilter) new IntegerFilter().setEquals(FAILURE.getId())); assertThatScenarioExecutionAtIndexSelectedByCriteria(scenarioExecutionCriteria, 2); } - public static Stream selectWithJoinToMessageHeader() { + public static Stream selectWithSelectiveJoinMessageHeader() { return Stream.of( arguments("83def191b1dda4c79c00ae4c443f0ca2", 0), arguments(TRACEPARENT.toLowerCase() + "=" + MESSAGE_1_TRACEPARENT.toLowerCase(), 1), @@ -267,7 +304,7 @@ public static Stream selectWithJoinToMessageHeader() { @MethodSource @ParameterizedTest - void selectWithJoinToMessageHeader(String headerFilterPattern, int expectedIndex) { + void selectWithSelectiveJoinMessageHeader(String headerFilterPattern, int expectedIndex) { var scenarioExecutionCriteria = new ScenarioExecutionCriteria(); scenarioExecutionCriteria.setHeaders(headerFilterPattern); @@ -275,7 +312,7 @@ void selectWithJoinToMessageHeader(String headerFilterPattern, int expectedIndex } @Test - void selectWithJoinToMessageHeaderMultipleCriteria() { + void selectWithSelectiveJoinMessageHeaderMultipleCriteria() { var scenarioExecutionCriteria = new ScenarioExecutionCriteria(); scenarioExecutionCriteria.setHeaders(SOURCE + "=" + SOURCE_VALUE); @@ -313,7 +350,7 @@ void testPagination(int pageSize, int expectedTotalPages) { void selectSecondPage() { Page testResultPage = fixture.findByCriteria( new ScenarioExecutionCriteria(), - PageRequest.of(1, 1, Sort.by(ASC, TestResult_.ID)) + PageRequest.of(1, 1, Sort.by(ASC, ScenarioExecution_.EXECUTION_ID)) ); assertThat(testResultPage.getTotalPages()).isEqualTo(3); @@ -383,6 +420,85 @@ private void testSort(Direction direction, String[] propertyNames, int[] indexOr } } + @Nested + class FindByCriteria_withResultDetailsConfiguration { + + public static Stream selectRootEntityOnly() { + return Stream.of( + arguments( + new ScenarioExecutionQueryService.ResultDetailsConfiguration(false, false, false, false), + (Consumer) scenarioExecution -> { + assertThatThrownBy(() -> scenarioExecution.getScenarioParameters().isEmpty()).isInstanceOf(LazyInitializationException.class); + assertThatThrownBy(() -> scenarioExecution.getScenarioActions().isEmpty()).isInstanceOf(LazyInitializationException.class); + assertThatThrownBy(() -> scenarioExecution.getScenarioMessages().isEmpty()).isInstanceOf(LazyInitializationException.class); + } + ), + arguments( + new ScenarioExecutionQueryService.ResultDetailsConfiguration(true, false, false, false), + (Consumer) scenarioExecution -> { + assertThatThrownBy(() -> scenarioExecution.getScenarioParameters().isEmpty()).isInstanceOf(LazyInitializationException.class); + assertThat(scenarioExecution.getScenarioActions()).isNotEmpty(); + assertThatThrownBy(() -> scenarioExecution.getScenarioMessages().isEmpty()).isInstanceOf(LazyInitializationException.class); + } + ), + arguments( + new ScenarioExecutionQueryService.ResultDetailsConfiguration(false, true, false, false), + (Consumer) scenarioExecution -> { + assertThatThrownBy(() -> scenarioExecution.getScenarioParameters().isEmpty()).isInstanceOf(LazyInitializationException.class); + assertThatThrownBy(() -> scenarioExecution.getScenarioActions().isEmpty()).isInstanceOf(LazyInitializationException.class); + assertThat(scenarioExecution.getScenarioMessages()).isNotEmpty(); + scenarioExecution.getScenarioMessages().forEach(scenarioMessage -> + assertThatThrownBy(() -> scenarioMessage.getHeaders().isEmpty()).isInstanceOf(LazyInitializationException.class)); + } + ), + arguments( + new ScenarioExecutionQueryService.ResultDetailsConfiguration(false, false, true, false), + (Consumer) scenarioExecution -> { + assertThatThrownBy(() -> scenarioExecution.getScenarioParameters().isEmpty()).isInstanceOf(LazyInitializationException.class); + assertThatThrownBy(() -> scenarioExecution.getScenarioActions().isEmpty()).isInstanceOf(LazyInitializationException.class); + assertThat(scenarioExecution.getScenarioMessages()).isNotEmpty(); + scenarioExecution.getScenarioMessages().forEach(scenarioMessage -> + assertThat(scenarioMessage.getHeaders()).isNotEmpty()); + } + ), + arguments( + new ScenarioExecutionQueryService.ResultDetailsConfiguration(false, false, false, true), + (Consumer) scenarioExecution -> { + assertThat(scenarioExecution.getScenarioParameters()).isNotEmpty(); + assertThatThrownBy(() -> scenarioExecution.getScenarioActions().isEmpty()).isInstanceOf(LazyInitializationException.class); + assertThatThrownBy(() -> scenarioExecution.getScenarioMessages().isEmpty()).isInstanceOf(LazyInitializationException.class); + } + ) + ); + } + + @MethodSource + @ParameterizedTest + void selectRootEntityOnly(ScenarioExecutionQueryService.ResultDetailsConfiguration resultDetailsConfiguration, Consumer verifier) { + var scenarioExecutionCriteria = new ScenarioExecutionCriteria(); + Page scenarioExecutionPage = fixture.findByCriteria( + scenarioExecutionCriteria, + unpaged(), + resultDetailsConfiguration + ); + + assertThat(scenarioExecutionPage) + .asInstanceOf(type(Page.class)) + .satisfies( + p -> assertThat(p.getTotalPages()).isEqualTo(1), + p -> assertThat(p.getTotalElements()).isEqualTo(3), + p -> assertThat(p.getContent()).hasSize(3) + ); + + var content = scenarioExecutionPage.getContent().stream().toList(); + assertThat(content).hasSize(3); + for (var scenarioExecution : content) { + assertThat(scenarioExecution.getTestResult().getStatus()).isNotNull(); + verifier.accept(scenarioExecution); + } + } + } + @AfterEach void afterEachTeardown() { scenarioExecutionRepository.deleteAll(scenarioExecutions); @@ -391,8 +507,15 @@ void afterEachTeardown() { 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)); + assertThat(scenarioExecutionPage) + .asInstanceOf(type(Page.class)) + .satisfies( + p -> assertThat(p.getTotalPages()).isEqualTo(1), + p -> assertThat(p.getTotalElements()).isEqualTo(1), + p -> assertThat(p.getContent()) + .hasSize(1) + .first() + .isEqualTo(scenarioExecutions.get(index)) + ); } } diff --git a/simulator-spring-boot/src/test/java/org/citrusframework/simulator/web/rest/MessageHeaderResourceIT.java b/simulator-spring-boot/src/test/java/org/citrusframework/simulator/web/rest/MessageHeaderResourceIT.java index 84ef8cd3d..ae41d534a 100644 --- a/simulator-spring-boot/src/test/java/org/citrusframework/simulator/web/rest/MessageHeaderResourceIT.java +++ b/simulator-spring-boot/src/test/java/org/citrusframework/simulator/web/rest/MessageHeaderResourceIT.java @@ -99,6 +99,7 @@ public static MessageHeader createEntity(EntityManager entityManager) { message = TestUtil.findAll(entityManager, Message.class).get(0); } messageHeader.setMessage(message); + message.addHeader(messageHeader); return messageHeader; } 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 bad31e1b0..39464588b 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 @@ -52,7 +52,9 @@ import static org.citrusframework.simulator.model.TestResult.Status.SUCCESS; import static org.citrusframework.simulator.web.rest.MessageResourceIT.DEFAULT_PAYLOAD; import static org.citrusframework.simulator.web.rest.MessageResourceIT.UPDATED_PAYLOAD; +import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasItem; +import static org.hamcrest.Matchers.hasSize; import static org.springframework.http.HttpStatus.OK; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; @@ -128,36 +130,43 @@ public static ScenarioExecution createUpdatedEntity(EntityManager entityManager) @BeforeEach void beforeEachSetup() { + var scenarioParameter = ScenarioParameterResourceIT.createEntity(entityManager); var testResult = TestResultResourceIT.createEntity(entityManager); + var scenarioAction = ScenarioActionResourceIT.createEntity(entityManager); + var message = MessageHeaderResourceIT.createEntity(entityManager).getMessage(); scenarioExecution = createEntity(entityManager) - .withTestResult(testResult); + .withTestResult(testResult) + .addScenarioParameter(scenarioParameter) + .addScenarioAction(scenarioAction) + .addScenarioMessage(message); + + scenarioExecutionRepository.saveAndFlush(scenarioExecution); } @Test @Transactional - void getAllScenarioExecutions() throws Exception { - // Initialize the database - scenarioExecutionRepository.saveAndFlush(scenarioExecution); - + void getAllScenarioExecutions_withAllDetails() throws Exception { // Get all the scenarioExecutionList mockMvc - .perform(get(ENTITY_API_URL + "?sort=executionId,desc")) + .perform(get(ENTITY_API_URL + "?sort=executionId,desc&includeActions=true&includeMessages=true&includeMessageHeaders=true&includeParameters=true")) .andExpect(status().isOk()) .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) - .andExpect(jsonPath("$.[*].executionId").value(hasItem(scenarioExecution.getExecutionId().intValue()))) - .andExpect(jsonPath("$.[*].startDate").value(hasItem(DEFAULT_START_DATE.toString()))) - .andExpect(jsonPath("$.[*].endDate").value(hasItem(DEFAULT_END_DATE.toString()))) - .andExpect(jsonPath("$.[*].scenarioName").value(hasItem(DEFAULT_SCENARIO_NAME))) - .andExpect(jsonPath("$.[*].testResult.status").value(SUCCESS.toString())); + .andExpect(jsonPath("$").value(hasSize(1))) + .andExpect(jsonPath("$.[0].executionId").value(equalTo(scenarioExecution.getExecutionId().intValue()))) + .andExpect(jsonPath("$.[0].startDate").value(equalTo(DEFAULT_START_DATE.toString()))) + .andExpect(jsonPath("$.[0].endDate").value(equalTo(DEFAULT_END_DATE.toString()))) + .andExpect(jsonPath("$.[0].scenarioName").value(equalTo(DEFAULT_SCENARIO_NAME))) + .andExpect(jsonPath("$.[0].testResult.status").value(equalTo(SUCCESS.toString()))) + .andExpect(jsonPath("$.[0].scenarioParameters").value(hasSize(1))) + .andExpect(jsonPath("$.[0].scenarioActions").value(hasSize(1))) + .andExpect(jsonPath("$.[0].scenarioMessages").value(hasSize(1))) + .andExpect(jsonPath("$.[0].scenarioMessages[0].headers").value(hasSize(1))); } @Test @Transactional void getScenarioExecution() throws Exception { - // Initialize the database - scenarioExecutionRepository.saveAndFlush(scenarioExecution); - // Get the scenarioExecution mockMvc .perform(get(ENTITY_API_URL_ID, scenarioExecution.getExecutionId())) @@ -173,9 +182,6 @@ void getScenarioExecution() throws Exception { @Test @Transactional void getScenarioExecutionsByIdFiltering() throws Exception { - // Initialize the database - scenarioExecutionRepository.saveAndFlush(scenarioExecution); - Long executionId = scenarioExecution.getExecutionId(); defaultScenarioExecutionShouldBeFound("executionId.equals=" + executionId); @@ -191,9 +197,6 @@ void getScenarioExecutionsByIdFiltering() throws Exception { @Test @Transactional void getAllScenarioExecutionsByStartDateIsEqualToSomething() throws Exception { - // Initialize the database - scenarioExecutionRepository.saveAndFlush(scenarioExecution); - // Get all the scenarioExecutionList where startDate equals to DEFAULT_START_DATE defaultScenarioExecutionShouldBeFound("startDate.equals=" + DEFAULT_START_DATE); @@ -204,9 +207,6 @@ void getAllScenarioExecutionsByStartDateIsEqualToSomething() throws Exception { @Test @Transactional void getAllScenarioExecutionsByStartDateIsInShouldWork() throws Exception { - // Initialize the database - scenarioExecutionRepository.saveAndFlush(scenarioExecution); - // Get all the scenarioExecutionList where startDate in DEFAULT_START_DATE or UPDATED_START_DATE defaultScenarioExecutionShouldBeFound("startDate.in=" + DEFAULT_START_DATE + "," + UPDATED_START_DATE); @@ -217,9 +217,6 @@ void getAllScenarioExecutionsByStartDateIsInShouldWork() throws Exception { @Test @Transactional void getAllScenarioExecutionsByStartDateIsNullOrNotNull() throws Exception { - // Initialize the database - scenarioExecutionRepository.saveAndFlush(scenarioExecution); - // Get all the scenarioExecutionList where startDate is not null defaultScenarioExecutionShouldBeFound("startDate.specified=true"); @@ -230,9 +227,6 @@ void getAllScenarioExecutionsByStartDateIsNullOrNotNull() throws Exception { @Test @Transactional void getAllTestParametersByCreatedDateIsGreaterThanOrEqualToSomething() throws Exception { - // Initialize the database - scenarioExecutionRepository.saveAndFlush(scenarioExecution); - // Get all the testParameterList where startDate is greater than or equal to DEFAULT_CREATED_DATE defaultScenarioExecutionShouldBeFound("startDate.greaterThanOrEqual=" + DEFAULT_START_DATE); @@ -243,9 +237,6 @@ void getAllTestParametersByCreatedDateIsGreaterThanOrEqualToSomething() throws E @Test @Transactional void getAllTestParametersByCreatedDateIsLessThanOrEqualToSomething() throws Exception { - // Initialize the database - scenarioExecutionRepository.saveAndFlush(scenarioExecution); - // Get all the testParameterList where startDate is less than or equal to DEFAULT_CREATED_DATE defaultScenarioExecutionShouldBeFound("startDate.lessThanOrEqual=" + DEFAULT_START_DATE); @@ -256,9 +247,6 @@ void getAllTestParametersByCreatedDateIsLessThanOrEqualToSomething() throws Exce @Test @Transactional void getAllScenarioExecutionsByEndDateIsEqualToSomething() throws Exception { - // Initialize the database - scenarioExecutionRepository.saveAndFlush(scenarioExecution); - // Get all the scenarioExecutionList where endDate equals to DEFAULT_END_DATE defaultScenarioExecutionShouldBeFound("endDate.equals=" + DEFAULT_END_DATE); @@ -269,9 +257,6 @@ void getAllScenarioExecutionsByEndDateIsEqualToSomething() throws Exception { @Test @Transactional void getAllScenarioExecutionsByEndDateIsInShouldWork() throws Exception { - // Initialize the database - scenarioExecutionRepository.saveAndFlush(scenarioExecution); - // Get all the scenarioExecutionList where endDate in DEFAULT_END_DATE or UPDATED_END_DATE defaultScenarioExecutionShouldBeFound("endDate.in=" + DEFAULT_END_DATE + "," + UPDATED_END_DATE); @@ -282,9 +267,6 @@ void getAllScenarioExecutionsByEndDateIsInShouldWork() throws Exception { @Test @Transactional void getAllScenarioExecutionsByEndDateIsNullOrNotNull() throws Exception { - // Initialize the database - scenarioExecutionRepository.saveAndFlush(scenarioExecution); - // Get all the scenarioExecutionList where endDate is not null defaultScenarioExecutionShouldBeFound("endDate.specified=true"); @@ -295,9 +277,6 @@ void getAllScenarioExecutionsByEndDateIsNullOrNotNull() throws Exception { @Test @Transactional void getAllTestParametersByLastModifiedDateIsGreaterThanOrEqualToSomething() throws Exception { - // Initialize the database - scenarioExecutionRepository.saveAndFlush(scenarioExecution); - // Get all the testParameterList where endDate is greater than or equal to DEFAULT_LAST_MODIFIED_DATE defaultScenarioExecutionShouldBeFound("endDate.greaterThanOrEqual=" + DEFAULT_END_DATE); @@ -308,9 +287,6 @@ void getAllTestParametersByLastModifiedDateIsGreaterThanOrEqualToSomething() thr @Test @Transactional void getAllTestParametersByLastModifiedDateIsLessThanOrEqualToSomething() throws Exception { - // Initialize the database - scenarioExecutionRepository.saveAndFlush(scenarioExecution); - // Get all the testParameterList where endDate is less than or equal to DEFAULT_LAST_MODIFIED_DATE defaultScenarioExecutionShouldBeFound("endDate.lessThanOrEqual=" + DEFAULT_END_DATE); @@ -321,9 +297,6 @@ void getAllTestParametersByLastModifiedDateIsLessThanOrEqualToSomething() throws @Test @Transactional void getAllScenarioExecutionsByScenarioNameIsEqualToSomething() throws Exception { - // Initialize the database - scenarioExecutionRepository.saveAndFlush(scenarioExecution); - // Get all the scenarioExecutionList where scenarioName equals to DEFAULT_SCENARIO_NAME defaultScenarioExecutionShouldBeFound("scenarioName.equals=" + DEFAULT_SCENARIO_NAME); @@ -334,9 +307,6 @@ void getAllScenarioExecutionsByScenarioNameIsEqualToSomething() throws Exception @Test @Transactional void getAllScenarioExecutionsByScenarioNameIsInShouldWork() throws Exception { - // Initialize the database - scenarioExecutionRepository.saveAndFlush(scenarioExecution); - // Get all the scenarioExecutionList where scenarioName in DEFAULT_SCENARIO_NAME or UPDATED_SCENARIO_NAME defaultScenarioExecutionShouldBeFound("scenarioName.in=" + DEFAULT_SCENARIO_NAME + "," + UPDATED_SCENARIO_NAME); @@ -347,9 +317,6 @@ void getAllScenarioExecutionsByScenarioNameIsInShouldWork() throws Exception { @Test @Transactional void getAllScenarioExecutionsByScenarioNameIsNullOrNotNull() throws Exception { - // Initialize the database - scenarioExecutionRepository.saveAndFlush(scenarioExecution); - // Get all the scenarioExecutionList where scenarioName is not null defaultScenarioExecutionShouldBeFound("scenarioName.specified=true"); @@ -360,9 +327,6 @@ void getAllScenarioExecutionsByScenarioNameIsNullOrNotNull() throws Exception { @Test @Transactional void getAllScenarioExecutionsByScenarioNameContainsSomething() throws Exception { - // Initialize the database - scenarioExecutionRepository.saveAndFlush(scenarioExecution); - // Get all the scenarioExecutionList where scenarioName contains DEFAULT_SCENARIO_NAME defaultScenarioExecutionShouldBeFound("scenarioName.contains=" + DEFAULT_SCENARIO_NAME); @@ -373,9 +337,6 @@ void getAllScenarioExecutionsByScenarioNameContainsSomething() throws Exception @Test @Transactional void getAllScenarioExecutionsByScenarioNameNotContainsSomething() throws Exception { - // Initialize the database - scenarioExecutionRepository.saveAndFlush(scenarioExecution); - // Get all the scenarioExecutionList where scenarioName does not contain DEFAULT_SCENARIO_NAME defaultScenarioExecutionShouldNotBeFound("scenarioName.doesNotContain=" + DEFAULT_SCENARIO_NAME); @@ -386,9 +347,6 @@ void getAllScenarioExecutionsByScenarioNameNotContainsSomething() throws Excepti @Test @Transactional void getAllScenarioExecutionsByStatusIsEqualToSomething() throws Exception { - // Initialize the database - scenarioExecutionRepository.saveAndFlush(scenarioExecution); - // Get all the scenarioExecutionList where status equals to DEFAULT_STATUS defaultScenarioExecutionShouldBeFound("status.equals=" + DEFAULT_STATUS.getId()); @@ -399,9 +357,6 @@ void getAllScenarioExecutionsByStatusIsEqualToSomething() throws Exception { @Test @Transactional void getAllScenarioExecutionsByStatusIsInShouldWork() throws Exception { - // Initialize the database - scenarioExecutionRepository.saveAndFlush(scenarioExecution); - // Get all the scenarioExecutionList where status in DEFAULT_STATUS or UPDATED_STATUS defaultScenarioExecutionShouldBeFound("status.in=" + DEFAULT_STATUS.getId() + "," + UPDATED_STATUS.getId()); @@ -412,9 +367,6 @@ void getAllScenarioExecutionsByStatusIsInShouldWork() throws Exception { @Test @Transactional void getAllScenarioExecutionsByStatusIsNullOrNotNull() throws Exception { - // Initialize the database - scenarioExecutionRepository.saveAndFlush(scenarioExecution); - // Get all the scenarioExecutionList where status is not null defaultScenarioExecutionShouldBeFound("status.specified=true"); @@ -425,18 +377,8 @@ void getAllScenarioExecutionsByStatusIsNullOrNotNull() throws Exception { @Test @Transactional void getAllScenarioExecutionsByScenarioActionIsEqualToSomething() throws Exception { - ScenarioAction scenarioAction; - if (TestUtil.findAll(entityManager, ScenarioAction.class).isEmpty()) { - scenarioExecutionRepository.saveAndFlush(scenarioExecution); - scenarioAction = ScenarioActionResourceIT.createEntity(entityManager); - } else { - scenarioAction = TestUtil.findAll(entityManager, ScenarioAction.class).get(0); - } - entityManager.persist(scenarioAction); - entityManager.flush(); - scenarioExecution.addScenarioAction(scenarioAction); - scenarioExecutionRepository.saveAndFlush(scenarioExecution); - Long scenarioActionId = scenarioAction.getActionId(); + Long scenarioActionId = TestUtil.findAll(entityManager, ScenarioAction.class).get(0).getActionId(); + // Get all the scenarioExecutionList where scenarioAction equals to scenarioActionId defaultScenarioExecutionShouldBeFound("scenarioActionsId.equals=" + scenarioActionId); @@ -447,18 +389,8 @@ void getAllScenarioExecutionsByScenarioActionIsEqualToSomething() throws Excepti @Test @Transactional void getAllScenarioExecutionsByScenarioMessagesIsEqualToSomething() throws Exception { - Message scenarioMessages; - if (TestUtil.findAll(entityManager, Message.class).isEmpty()) { - scenarioExecutionRepository.saveAndFlush(scenarioExecution); - scenarioMessages = MessageResourceIT.createEntity(entityManager); - } else { - scenarioMessages = TestUtil.findAll(entityManager, Message.class).get(0); - } - entityManager.persist(scenarioMessages); - entityManager.flush(); - scenarioExecution.addScenarioMessage(scenarioMessages); - scenarioExecutionRepository.saveAndFlush(scenarioExecution); - Long scenarioMessagesId = scenarioMessages.getMessageId(); + Long scenarioMessagesId = TestUtil.findAll(entityManager, Message.class).get(0).getMessageId(); + // Get all the scenarioExecutionList where scenarioMessages equals to scenarioMessagesId defaultScenarioExecutionShouldBeFound("scenarioMessagesId.equals=" + scenarioMessagesId); @@ -469,18 +401,6 @@ void getAllScenarioExecutionsByScenarioMessagesIsEqualToSomething() throws Excep @Test @Transactional void getAllScenarioExecutionsByScenarioMessagesPayloadIsEqualToSomething() throws Exception { - Message scenarioMessages; - if (TestUtil.findAll(entityManager, Message.class).isEmpty()) { - scenarioExecutionRepository.saveAndFlush(scenarioExecution); - scenarioMessages = MessageResourceIT.createEntity(entityManager); - } else { - scenarioMessages = TestUtil.findAll(entityManager, Message.class).get(0); - } - entityManager.persist(scenarioMessages); - entityManager.flush(); - scenarioExecution.addScenarioMessage(scenarioMessages); - scenarioExecutionRepository.saveAndFlush(scenarioExecution); - // Get all the scenarioExecutionList where payload equals the default payload defaultScenarioExecutionShouldBeFound("scenarioMessagesPayload.equals=" + DEFAULT_PAYLOAD); @@ -491,18 +411,8 @@ void getAllScenarioExecutionsByScenarioMessagesPayloadIsEqualToSomething() throw @Test @Transactional void getAllScenarioExecutionsByScenarioParametersIsEqualToSomething() throws Exception { - ScenarioParameter scenarioParameters; - if (TestUtil.findAll(entityManager, ScenarioParameter.class).isEmpty()) { - scenarioExecutionRepository.saveAndFlush(scenarioExecution); - scenarioParameters = ScenarioParameterResourceIT.createEntity(entityManager); - } else { - scenarioParameters = TestUtil.findAll(entityManager, ScenarioParameter.class).get(0); - } - entityManager.persist(scenarioParameters); - entityManager.flush(); - scenarioExecution.addScenarioParameter(scenarioParameters); - scenarioExecutionRepository.saveAndFlush(scenarioExecution); - Long scenarioParametersId = scenarioParameters.getParameterId(); + Long scenarioParametersId = TestUtil.findAll(entityManager, ScenarioParameter.class).get(0).getParameterId(); + // Get all the scenarioExecutionList where scenarioParameters equals to scenarioParametersId defaultScenarioExecutionShouldBeFound("scenarioParametersId.equals=" + scenarioParametersId); @@ -570,6 +480,7 @@ class CorrectTimeOnScenarioExecution { private MockMvc mockMvc; @Test + @Transactional void shouldInvokeScenario() throws Exception { String mockEndpointResult = mockMvc .perform(get("/services/rest/api/v1/ZmNrqCkoGQ")) @@ -581,7 +492,7 @@ void shouldInvokeScenario() throws Exception { assertThat(mockEndpointResult).contains("E5a084sOZw7"); String scenarioExecutionsResult = mockMvc - .perform(get("/api/scenario-executions?includeActions=true&includeMessages=true&includeParameters=true")) + .perform(get("/api/scenario-executions?includeActions=true&includeMessages=true&scenarioMessagesPayload.equals=E5a084sOZw7")) .andExpect(status().isOk()) .andReturn() .getResponse() @@ -606,6 +517,7 @@ void shouldInvokeScenario() throws Exception { @Scenario("DEFAULT_SCENARIO") public static class HelloScenario extends AbstractSimulatorScenario { + @Override public void run(ScenarioRunner scenario) { scenario.$(scenario.http() diff --git a/simulator-spring-boot/src/test/java/org/citrusframework/simulator/web/rest/ScenarioExecutionResourceTest.java b/simulator-spring-boot/src/test/java/org/citrusframework/simulator/web/rest/ScenarioExecutionResourceTest.java index 79e8109b4..5fa52d20f 100644 --- a/simulator-spring-boot/src/test/java/org/citrusframework/simulator/web/rest/ScenarioExecutionResourceTest.java +++ b/simulator-spring-boot/src/test/java/org/citrusframework/simulator/web/rest/ScenarioExecutionResourceTest.java @@ -16,11 +16,9 @@ package org.citrusframework.simulator.web.rest; -import org.citrusframework.simulator.model.Message; -import org.citrusframework.simulator.model.ScenarioAction; import org.citrusframework.simulator.model.ScenarioExecution; -import org.citrusframework.simulator.model.ScenarioParameter; import org.citrusframework.simulator.service.ScenarioExecutionQueryService; +import org.citrusframework.simulator.service.ScenarioExecutionQueryService.ResultDetailsConfiguration; import org.citrusframework.simulator.service.ScenarioExecutionService; import org.citrusframework.simulator.service.criteria.ScenarioExecutionCriteria; import org.citrusframework.simulator.web.rest.dto.ScenarioExecutionDTO; @@ -29,21 +27,26 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; +import org.springframework.http.ResponseEntity; import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; +import java.util.List; + import static java.lang.Boolean.FALSE; import static java.lang.Boolean.TRUE; import static java.util.Collections.singletonList; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentCaptor.captor; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.mock; import static org.springframework.http.HttpStatus.OK; +import static org.springframework.web.context.request.RequestContextHolder.setRequestAttributes; @ExtendWith({MockitoExtension.class}) class ScenarioExecutionResourceTest { @@ -61,7 +64,8 @@ class ScenarioExecutionResourceTest { @BeforeEach void beforeEachSetup() { - fixture = new ScenarioExecutionResource(scenarioExecutionServiceMock, scenarioExecutionQueryServiceMock, scenarioExecutionMapperMock); + fixture = new ScenarioExecutionResource(scenarioExecutionServiceMock, + scenarioExecutionQueryServiceMock, scenarioExecutionMapperMock); } @Nested @@ -77,61 +81,87 @@ class GetAllScenarioExecutions { private ScenarioExecutionDTO scenarioExecutionDTOMock; private ScenarioExecution scenarioExecution; + private ArgumentCaptor resultDetailsConfigurationArgumentCaptor; @BeforeEach void beforeEachSetup() { var request = new MockHttpServletRequest(); - RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request)); + setRequestAttributes(new ServletRequestAttributes(request)); scenarioExecution = new ScenarioExecution(); - scenarioExecution.getScenarioActions().add(mock(ScenarioAction.class)); - scenarioExecution.getScenarioMessages().add(mock(Message.class)); - scenarioExecution.getScenarioParameters().add(mock(ScenarioParameter.class)); - var scenarioExecutions = new PageImpl<>(singletonList(scenarioExecution)); - doReturn(scenarioExecutions).when(scenarioExecutionQueryServiceMock).findByCriteria(criteriaMock, pageableMock); - doReturn(scenarioExecutionDTOMock).when(scenarioExecutionMapperMock).toDto(scenarioExecution); + resultDetailsConfigurationArgumentCaptor = captor(); + doReturn(scenarioExecutions) + .when(scenarioExecutionQueryServiceMock) + .findByCriteria(eq(criteriaMock), eq(pageableMock), resultDetailsConfigurationArgumentCaptor.capture()); + + doReturn(scenarioExecutionDTOMock) + .when(scenarioExecutionMapperMock) + .toDto(scenarioExecution); } @Test void stripsIncludedActions() { - var response = fixture.getAllScenarioExecutions(criteriaMock, FALSE, TRUE, TRUE, pageableMock); + var response = fixture.getAllScenarioExecutions(criteriaMock, FALSE, TRUE, TRUE, TRUE, pageableMock); + verifyResponseContainsDtos(response); - assertThat(response) + assertThat(resultDetailsConfigurationArgumentCaptor.getValue()) + .isNotNull() .satisfies( - r -> assertThat(r.getStatusCode()).isEqualTo(OK), - r -> assertThat(r.getBody()) - .singleElement() - .isEqualTo(scenarioExecutionDTOMock) + r -> assertThat(r.includeActions()).isFalse(), + r -> assertThat(r.includeMessages()).isTrue(), + r -> assertThat(r.includeMessageHeaders()).isTrue(), + r -> assertThat(r.includeParameters()).isTrue() ); - - assertThat(scenarioExecution.getScenarioActions()).isEmpty(); - assertThat(scenarioExecution.getScenarioMessages()).isNotEmpty(); - assertThat(scenarioExecution.getScenarioParameters()).isNotEmpty(); } @Test void stripsIncludedMessages() { - var response = fixture.getAllScenarioExecutions(criteriaMock, TRUE, FALSE, TRUE, pageableMock); + var response = fixture.getAllScenarioExecutions(criteriaMock, TRUE, FALSE, TRUE, TRUE, pageableMock); + verifyResponseContainsDtos(response); - assertThat(response) + assertThat(resultDetailsConfigurationArgumentCaptor.getValue()) + .isNotNull() .satisfies( - r -> assertThat(r.getStatusCode()).isEqualTo(OK), - r -> assertThat(r.getBody()) - .singleElement() - .isEqualTo(scenarioExecutionDTOMock) + r -> assertThat(r.includeActions()).isTrue(), + r -> assertThat(r.includeMessages()).isFalse(), + r -> assertThat(r.includeMessageHeaders()).isTrue(), + r -> assertThat(r.includeParameters()).isTrue() ); + } - assertThat(scenarioExecution.getScenarioActions()).isNotEmpty(); - assertThat(scenarioExecution.getScenarioMessages()).isEmpty(); - assertThat(scenarioExecution.getScenarioParameters()).isNotEmpty(); + @Test + void stripsIncludedMessageHeaderss() { + var response = fixture.getAllScenarioExecutions(criteriaMock, TRUE, TRUE, FALSE, TRUE, pageableMock); + verifyResponseContainsDtos(response); + + assertThat(resultDetailsConfigurationArgumentCaptor.getValue()) + .isNotNull() + .satisfies( + r -> assertThat(r.includeActions()).isTrue(), + r -> assertThat(r.includeMessages()).isTrue(), + r -> assertThat(r.includeMessageHeaders()).isFalse(), + r -> assertThat(r.includeParameters()).isTrue() + ); } @Test void stripsIncludedParameters() { - var response = fixture.getAllScenarioExecutions(criteriaMock, TRUE, TRUE, FALSE, pageableMock); + var response = fixture.getAllScenarioExecutions(criteriaMock, TRUE, TRUE, TRUE, FALSE, pageableMock); + verifyResponseContainsDtos(response); + + assertThat(resultDetailsConfigurationArgumentCaptor.getValue()) + .isNotNull() + .satisfies( + r -> assertThat(r.includeActions()).isTrue(), + r -> assertThat(r.includeMessages()).isTrue(), + r -> assertThat(r.includeMessageHeaders()).isTrue(), + r -> assertThat(r.includeParameters()).isFalse() + ); + } + private void verifyResponseContainsDtos(ResponseEntity> response) { assertThat(response) .satisfies( r -> assertThat(r.getStatusCode()).isEqualTo(OK), @@ -139,10 +169,6 @@ void stripsIncludedParameters() { .singleElement() .isEqualTo(scenarioExecutionDTOMock) ); - - assertThat(scenarioExecution.getScenarioActions()).isNotEmpty(); - assertThat(scenarioExecution.getScenarioMessages()).isNotEmpty(); - assertThat(scenarioExecution.getScenarioParameters()).isEmpty(); } } }