diff --git a/CHANGELOG.md b/CHANGELOG.md index dbe9d95c..e0297a32 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## [v3.20.3](https://github.com/bancolombia/scaffold-clean-architecture/tree/v3.20.3) (2024-11-25) + +[Full Changelog](https://github.com/bancolombia/scaffold-clean-architecture/compare/v3.20.2...v3.20.3) + +**Merged pull requests:** + +- fix\(build\): Update commons templates [\#590](https://github.com/bancolombia/scaffold-clean-architecture/pull/590) ([juparog](https://github.com/juparog)) + ## [v3.20.2](https://github.com/bancolombia/scaffold-clean-architecture/tree/v3.20.2) (2024-11-21) [Full Changelog](https://github.com/bancolombia/scaffold-clean-architecture/compare/v3.20.1...v3.20.2) diff --git a/gradle.properties b/gradle.properties index a21c4bd2..783614de 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ package=co.com.bancolombia -systemProp.version=3.20.2 +systemProp.version=3.20.3 simulateRest=true systemProp.sonar.gradle.skipCompile=true \ No newline at end of file diff --git a/src/main/java/co/com/bancolombia/Constants.java b/src/main/java/co/com/bancolombia/Constants.java index 073bb907..1f1694b4 100644 --- a/src/main/java/co/com/bancolombia/Constants.java +++ b/src/main/java/co/com/bancolombia/Constants.java @@ -28,7 +28,7 @@ public final class Constants { public static final String JACOCO_VERSION = "0.8.12"; public static final String SONAR_VERSION = "5.1.0.4882"; public static final String COBERTURA_VERSION = "4.0.0"; - public static final String PLUGIN_VERSION = "3.20.2"; + public static final String PLUGIN_VERSION = "3.20.3"; public static final String DEPENDENCY_CHECK_VERSION = "11.1.0"; public static final String PITEST_VERSION = "1.15.0"; // custom diff --git a/src/main/resources/driven-adapter/async-event-bus/build.gradle.mustache b/src/main/resources/driven-adapter/async-event-bus/build.gradle.mustache index ec64e70f..f336eef1 100644 --- a/src/main/resources/driven-adapter/async-event-bus/build.gradle.mustache +++ b/src/main/resources/driven-adapter/async-event-bus/build.gradle.mustache @@ -1,5 +1,8 @@ dependencies { implementation project(':model') + {{#eda}} + implementation 'io.cloudevents:cloudevents-json-jackson:4.0.1' + {{/eda}} {{#rabbitmq}} implementation 'org.reactivecommons:async-commons-rabbit-starter:{{REACTIVE_COMMONS_VERSION}}' {{/rabbitmq}} diff --git a/src/main/resources/driven-adapter/async-event-bus/definition.json b/src/main/resources/driven-adapter/async-event-bus/definition.json index 1e815b00..de02bdb6 100644 --- a/src/main/resources/driven-adapter/async-event-bus/definition.json +++ b/src/main/resources/driven-adapter/async-event-bus/definition.json @@ -6,6 +6,8 @@ "driven-adapter/async-event-bus/events-gateway.java.mustache": "domain/model/src/main/java/{{packagePath}}/model/events/gateways/EventsGateway.java", "driven-adapter/async-event-bus/reactive-events-gateway.java.mustache": "infrastructure/driven-adapters/async-event-bus/src/main/java/{{packagePath}}/events/ReactiveEventsGateway.java", "driven-adapter/async-event-bus/reactive-direct-async-gateway.java.mustache": "infrastructure/driven-adapters/async-event-bus/src/main/java/{{packagePath}}/events/ReactiveDirectAsyncGateway.java", + "driven-adapter/async-event-bus/reactive-direct-async-gateway.unit.test.java.mustache": "infrastructure/driven-adapters/async-event-bus/src/test/java/{{packagePath}}/events/ReactiveDirectAsyncGatewayTest.java", + "driven-adapter/async-event-bus/reactive-events-gateway.unit.test.java.mustache": "infrastructure/driven-adapters/async-event-bus/src/test/java/{{packagePath}}/events/ReactiveEventsGatewayTest.java", "driven-adapter/async-event-bus/build.gradle.mustache": "infrastructure/driven-adapters/async-event-bus/build.gradle" } } diff --git a/src/main/resources/driven-adapter/async-event-bus/reactive-direct-async-gateway.unit.test.java.mustache b/src/main/resources/driven-adapter/async-event-bus/reactive-direct-async-gateway.unit.test.java.mustache new file mode 100644 index 00000000..fb49da2b --- /dev/null +++ b/src/main/resources/driven-adapter/async-event-bus/reactive-direct-async-gateway.unit.test.java.mustache @@ -0,0 +1,118 @@ +package {{package}}.events; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.reactivecommons.async.api.DirectAsyncGateway; +import reactor.core.publisher.Mono; +{{#eda}} +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import io.cloudevents.CloudEvent; +import io.cloudevents.core.builder.CloudEventBuilder; +import io.cloudevents.jackson.JsonCloudEventData; + +import java.net.URI; +import java.time.OffsetDateTime; +import java.util.UUID; +{{/eda}} +{{^eda}} +import org.reactivecommons.api.domain.Command; +import org.reactivecommons.async.api.AsyncQuery; +{{/eda}} + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; + +public class ReactiveDirectAsyncGatewayTest { + + @Mock + private DirectAsyncGateway directAsyncGateway; + {{#eda}} + @Mock + private ObjectMapper objectMapper; + {{/eda}} + + private ReactiveDirectAsyncGateway gateway; + + @BeforeEach + public void setUp() { + MockitoAnnotations.openMocks(this); + gateway = new ReactiveDirectAsyncGateway(directAsyncGateway{{#eda}}, objectMapper{{/eda}}); + } + + @Test + public void testRunRemoteJobSendsCommand() {{#eda}}throws Exception{{/eda}} { + Object command = new Object() { + public String toString() { + return "testCommand"; + } + }; + {{#eda}} + when(objectMapper.valueToTree(command)).thenReturn(mock(ObjectNode.class)); + when(directAsyncGateway.sendCommand(any(CloudEvent.class), any(String.class))).thenReturn(Mono.empty()); + {{/eda}} + {{^eda}} + when(directAsyncGateway.sendCommand(any(Command.class), any(String.class))).thenReturn(Mono.empty()); + {{/eda}} + + gateway.runRemoteJob(command).block(); + + {{#eda}} + ArgumentCaptor eventCaptor = ArgumentCaptor.forClass(CloudEvent.class); + verify(directAsyncGateway, times(1)).sendCommand(eventCaptor.capture(), eq(ReactiveDirectAsyncGateway.TARGET_NAME)); + CloudEvent cloudEvent = eventCaptor.getValue(); + {{/eda}} + {{^eda}} + ArgumentCaptor commandCaptor = ArgumentCaptor.forClass(Command.class); + verify(directAsyncGateway, times(1)).sendCommand(commandCaptor.capture(), eq(ReactiveDirectAsyncGateway.TARGET_NAME)); + Command capturedCommand = commandCaptor.getValue(); + assertEquals(ReactiveDirectAsyncGateway.SOME_COMMAND_NAME, capturedCommand.getName()); + {{/eda}} + } + + @Test + public void testRequestForRemoteDataSendsQuery() {{#eda}}throws JsonProcessingException{{/eda}} { + Object query = new Object() { + public String toString() { + return "testQuery"; + } + }; + {{#eda}} + ObjectNode mockNode = mock(ObjectNode.class); + when(objectMapper.valueToTree(query)).thenReturn(mockNode); + when(objectMapper.createObjectNode()).thenReturn(new ObjectMapper().createObjectNode()); + + CloudEvent mockCloudEvent = CloudEventBuilder.v1() + .withId(UUID.randomUUID().toString()) + .withSource(URI.create("https://spring.io/foos")) + .withType(ReactiveDirectAsyncGateway.SOME_QUERY_NAME) + .withTime(OffsetDateTime.now()) + .withData("application/json", JsonCloudEventData.wrap(objectMapper.createObjectNode().put("key", "value"))) + .build(); + + when(directAsyncGateway.requestReply(any(CloudEvent.class), any(String.class), eq(CloudEvent.class))) + .thenReturn(Mono.just(mockCloudEvent)); + + gateway.requestForRemoteData(query).block(); + + ArgumentCaptor eventCaptor = ArgumentCaptor.forClass(CloudEvent.class); + verify(directAsyncGateway, times(1)).requestReply(eventCaptor.capture(), eq(ReactiveDirectAsyncGateway.TARGET_NAME), eq(CloudEvent.class)); + CloudEvent cloudEvent = eventCaptor.getValue(); + {{/eda}} + {{^eda}} + when(directAsyncGateway.requestReply(any(AsyncQuery.class), any(String.class), eq(Object.class))).thenReturn(Mono.just(new Object())); + + gateway.requestForRemoteData(query).block(); + + ArgumentCaptor queryCaptor = ArgumentCaptor.forClass(AsyncQuery.class); + verify(directAsyncGateway, times(1)).requestReply(queryCaptor.capture(), eq(ReactiveDirectAsyncGateway.TARGET_NAME), eq(Object.class)); + AsyncQuery capturedQuery = queryCaptor.getValue(); + assertEquals(ReactiveDirectAsyncGateway.SOME_QUERY_NAME, capturedQuery.getResource()); + {{/eda}} + } +} diff --git a/src/main/resources/driven-adapter/async-event-bus/reactive-events-gateway.unit.test.java.mustache b/src/main/resources/driven-adapter/async-event-bus/reactive-events-gateway.unit.test.java.mustache new file mode 100644 index 00000000..a9c6e487 --- /dev/null +++ b/src/main/resources/driven-adapter/async-event-bus/reactive-events-gateway.unit.test.java.mustache @@ -0,0 +1,124 @@ +package {{package}}.events; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import reactor.core.publisher.Mono; +import org.reactivecommons.api.domain.DomainEventBus; + +{{#eda}} +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import io.cloudevents.CloudEvent; +{{/eda}} +{{^eda}} +import org.reactivecommons.api.domain.DomainEvent; +{{/eda}} +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class ReactiveEventsGatewayTest { + + {{#eda}} + @Mock + private DomainEventBus domainEventBus; + + @Mock + private ObjectMapper objectMapper; + + private ReactiveEventsGateway gateway; + {{/eda}} + {{^eda}} + @Mock + private DomainEventBus domainEventBus; + + private ReactiveEventsGateway reactiveEventsGateway; + {{/eda}} + + @BeforeEach + public void setUp() { + MockitoAnnotations.openMocks(this); + {{#eda}} + gateway = new ReactiveEventsGateway(domainEventBus, objectMapper); + when(domainEventBus.emit(any(CloudEvent.class))).thenReturn(Mono.empty()); + {{/eda}} + {{^eda}} + reactiveEventsGateway = new ReactiveEventsGateway(domainEventBus); + {{/eda}} + } + + @Test + public void testEmitLogsEvent() { + Object event = new Object() { + @Override + public String toString() { + return "testEvent"; + } + }; + + {{#eda}} + when(objectMapper.valueToTree(event)).thenReturn(mock(ObjectNode.class)); + + gateway.emit(event).block(); + + verify(domainEventBus, times(1)).emit(any(CloudEvent.class)); + {{/eda}} + {{^eda}} + when(domainEventBus.emit(any(DomainEvent.class))).thenReturn(Mono.empty()); + + reactiveEventsGateway.emit(event).block(); + + verify(domainEventBus, times(1)).emit(any(DomainEvent.class)); + {{/eda}} + } + + {{#eda}} + @Test + public void testEmitConstructsCloudEvent() { + Object event = new Object() { + public String toString() { return "testEvent"; } + }; + + when(objectMapper.valueToTree(event)).thenReturn(mock(ObjectNode.class)); + + gateway.emit(event).block(); + + ArgumentCaptor eventCaptor = ArgumentCaptor.forClass(CloudEvent.class); + verify(domainEventBus, times(1)).emit(eventCaptor.capture()); + + CloudEvent cloudEvent = eventCaptor.getValue(); + assertEquals(ReactiveEventsGateway.SOME_EVENT_NAME, cloudEvent.getType()); + assertEquals("https://reactive-commons.org/foos", cloudEvent.getSource().toString()); + } + {{/eda}} + + {{^eda}} + @Test + public void testEmitConstructsDomainEvent() { + Object event = new Object() { + @Override + public String toString() { + return "testEvent"; + } + }; + + when(domainEventBus.emit(any(DomainEvent.class))).thenReturn(Mono.empty()); + + reactiveEventsGateway.emit(event).block(); + + ArgumentCaptor eventCaptor = ArgumentCaptor.forClass(DomainEvent.class); + verify(domainEventBus, times(1)).emit(eventCaptor.capture()); + + DomainEvent capturedEvent = eventCaptor.getValue(); + assertEquals(ReactiveEventsGateway.SOME_EVENT_NAME, capturedEvent.getName()); + assertEquals(event.toString(), capturedEvent.getData().toString()); + } + {{/eda}} + + + + +} diff --git a/src/main/resources/entry-point/async-event-handler/build.gradle.mustache b/src/main/resources/entry-point/async-event-handler/build.gradle.mustache index be182923..fac5e310 100644 --- a/src/main/resources/entry-point/async-event-handler/build.gradle.mustache +++ b/src/main/resources/entry-point/async-event-handler/build.gradle.mustache @@ -1,6 +1,9 @@ dependencies { implementation project(':model') implementation project(':usecase') + {{#eda}} + implementation 'io.cloudevents:cloudevents-json-jackson:4.0.1' + {{/eda}} {{#rabbitmq}} implementation 'org.reactivecommons:async-commons-rabbit-starter:{{REACTIVE_COMMONS_VERSION}}' {{/rabbitmq}}