Skip to content

Commit

Permalink
fix: use zoned time on AuditingEntity
Browse files Browse the repository at this point in the history
  • Loading branch information
Sterchi Daniel authored and bbortt committed Aug 13, 2024
1 parent 6e2ba0f commit b19c7c9
Show file tree
Hide file tree
Showing 8 changed files with 150 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,19 @@
* limitations under the License.
*/

package org.citrusframework.simulator.service.impl;
package org.citrusframework.simulator.common;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;

class TimeProvider {
import static java.time.ZoneOffset.UTC;

TimeProvider() {
// Separate class that allows mocking
}
/**
* Should be used whenever the current time is needed, to ensure consistent Date/Time values
*/
public class TimeProvider {

Instant getTimeNow() {
return LocalDateTime.now().toInstant(ZoneOffset.UTC);
public Instant getTimeNow() {
return LocalDateTime.now().toInstant(UTC);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import jakarta.persistence.EntityListeners;
import jakarta.persistence.MappedSuperclass;
import lombok.Data;
import org.citrusframework.simulator.common.TimeProvider;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
Expand All @@ -39,16 +40,18 @@
@JsonIgnoreProperties(value = {"createdDate", "lastModifiedDate"}, allowGetters = true)
public abstract class AbstractAuditingEntity<T, I> implements Serializable {

private static TimeProvider timeProvider = new TimeProvider();

@Serial
private static final long serialVersionUID = 1L;

@CreatedDate
@Column(name = "created_date", nullable = false, updatable = false)
private Instant createdDate = Instant.now();
private Instant createdDate = timeProvider.getTimeNow();

@LastModifiedDate
@Column(name = "last_modified_date")
private Instant lastModifiedDate = Instant.now();
private Instant lastModifiedDate = timeProvider.getTimeNow();

public static abstract class AuditingEntityBuilder<B extends AuditingEntityBuilder<B, E, A>, E extends AbstractAuditingEntity<E, A>, A> {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.citrusframework.TestAction;
import org.citrusframework.TestCase;
import org.citrusframework.exceptions.CitrusRuntimeException;
import org.citrusframework.simulator.common.TimeProvider;
import org.citrusframework.simulator.model.ScenarioAction;
import org.citrusframework.simulator.repository.ScenarioActionRepository;
import org.citrusframework.simulator.service.ScenarioActionService;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import jakarta.annotation.Nullable;
import org.citrusframework.exceptions.CitrusRuntimeException;
import org.citrusframework.simulator.common.TimeProvider;
import org.citrusframework.simulator.model.ScenarioExecution;
import org.citrusframework.simulator.model.ScenarioParameter;
import org.citrusframework.simulator.model.TestResult;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package org.citrusframework.simulator.model;

import org.assertj.core.data.TemporalUnitLessThanOffset;
import org.citrusframework.simulator.common.TimeProvider;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import static java.time.temporal.ChronoUnit.SECONDS;
import static org.assertj.core.api.Assertions.assertThat;

class AbstractAuditingEntityIT {

public static final TemporalUnitLessThanOffset LESS_THAN_1_SECOND = new TemporalUnitLessThanOffset(1, SECONDS);

AuditedEntity fixture;

@BeforeEach
void setup() {
fixture = new AuditedEntity();
}

@Test
void shouldUseCorrectTime() {
var timeProvider = new TimeProvider();
assertThat(fixture.getCreatedDate()).isCloseTo(timeProvider.getTimeNow(), LESS_THAN_1_SECOND);
assertThat(fixture.getLastModifiedDate()).isCloseTo(timeProvider.getTimeNow(), LESS_THAN_1_SECOND);
}

private static class AuditedEntity extends AbstractAuditingEntity<AuditedEntity, Long> {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.citrusframework.TestAction;
import org.citrusframework.TestCase;
import org.citrusframework.exceptions.CitrusRuntimeException;
import org.citrusframework.simulator.common.TimeProvider;
import org.citrusframework.simulator.model.ScenarioAction;
import org.citrusframework.simulator.model.ScenarioExecution;
import org.citrusframework.simulator.repository.ScenarioActionRepository;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package org.citrusframework.simulator.service.impl;

import org.citrusframework.exceptions.CitrusRuntimeException;
import org.citrusframework.simulator.common.TimeProvider;
import org.citrusframework.simulator.model.ScenarioExecution;
import org.citrusframework.simulator.model.ScenarioParameter;
import org.citrusframework.simulator.model.TestResult;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@

package org.citrusframework.simulator.web.rest;

import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.persistence.EntityManager;
import org.assertj.core.data.TemporalUnitLessThanOffset;
import org.citrusframework.simulator.IntegrationTest;
import org.citrusframework.simulator.model.Message;
import org.citrusframework.simulator.model.ScenarioAction;
Expand All @@ -25,7 +27,11 @@
import org.citrusframework.simulator.model.ScenarioParameter;
import org.citrusframework.simulator.model.TestResult;
import org.citrusframework.simulator.repository.ScenarioExecutionRepository;
import org.citrusframework.simulator.scenario.AbstractSimulatorScenario;
import org.citrusframework.simulator.scenario.Scenario;
import org.citrusframework.simulator.scenario.ScenarioRunner;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
Expand All @@ -34,11 +40,18 @@
import org.springframework.transaction.annotation.Transactional;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;

import static java.time.LocalDateTime.now;
import static java.time.temporal.ChronoUnit.SECONDS;
import static org.assertj.core.api.Assertions.assertThat;
import static org.citrusframework.simulator.model.TestResult.Status.FAILURE;
import static org.citrusframework.simulator.model.TestResult.Status.SUCCESS;
import static org.hamcrest.Matchers.hasItem;
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;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
Expand Down Expand Up @@ -520,4 +533,93 @@ void getNonExistingScenarioExecution() throws Exception {
// Get the scenarioExecution
mockMvc.perform(get(ENTITY_API_URL_ID, Long.MAX_VALUE)).andExpect(status().isNotFound());
}

@Nested
class CorrectTimeOnScenarioExecution {
public static final TemporalUnitLessThanOffset LESS_THAN_5_SECONDS = new TemporalUnitLessThanOffset(5, SECONDS);

@Autowired
private ObjectMapper objectMapper;

@Autowired
private MockMvc mockMvc;

@Test
void shouldInvokeScenario() throws Exception {
String mockEndpointResult = mockMvc
.perform(get("/services/rest/api/v1/ZmNrqCkoGQ"))
.andExpect(status().isOk())
.andReturn()
.getResponse()
.getContentAsString();

assertThat(mockEndpointResult).contains("E5a084sOZw7");

String scenarioExecutionsResult = mockMvc
.perform(get("/api/scenario-executions"))
.andExpect(status().isOk())
.andReturn()
.getResponse()
.getContentAsString();

List<ScenarioExecution> scenarioExecutions = objectMapper.readValue(scenarioExecutionsResult, ScenarioExecutions.class);

assertThat(scenarioExecutions)
.hasSize(1)
.anySatisfy(execution -> {
assertThat(execution.startDate()).isCloseTo(now(), LESS_THAN_5_SECONDS);
assertThat(execution.endDate()).isCloseTo(now(), LESS_THAN_5_SECONDS);
assertThat(execution.scenarioActions()).allSatisfy(action -> {
assertThat(action.startDate()).isCloseTo(now(), LESS_THAN_5_SECONDS);
assertThat(action.endDate()).isCloseTo(now(), LESS_THAN_5_SECONDS);
});
assertThat(execution.scenarioMessages()).anySatisfy(action -> {
assertThat(action.createdDate()).isCloseTo(now(), LESS_THAN_5_SECONDS);
});
});
}

@Scenario("DEFAULT_SCENARIO")
public static class HelloScenario extends AbstractSimulatorScenario {
@Override
public void run(ScenarioRunner scenario) {
scenario.$(scenario.http()
.receive()
.get()
.path("/services/rest/api/v1/ZmNrqCkoGQ"));

scenario.$(scenario.http()
.send()
.response(OK)
.message()
.body("E5a084sOZw7"));
}
}


public static class ScenarioExecutions extends ArrayList<ScenarioExecution> {
}

public record ScenarioExecution(
LocalDateTime startDate,
LocalDateTime endDate,
List<ScenarioActions> scenarioActions,
List<ScenarioMessages> scenarioMessages
) {

}

public record ScenarioActions(
LocalDateTime startDate,
LocalDateTime endDate
) {

}

public record ScenarioMessages(
LocalDateTime createdDate
) {

}
}
}

0 comments on commit b19c7c9

Please sign in to comment.