From 0b81bf5e45fdb2174df13ebc7c35aa1f016d5d4b Mon Sep 17 00:00:00 2001 From: Dhawal Kapil Date: Sun, 31 Jul 2022 18:10:51 +0530 Subject: [PATCH 1/3] BAEL-5230 Added code and test for Fauna IoT application article --- persistence-modules/fauna/pom.xml | 12 ++++ .../com/baeldung/healthapp/FaunaClients.java | 42 ++++++++++++++ .../healthapp/FaunaHealthApplication.java | 13 +++++ .../baeldung/healthapp/domain/HealthData.java | 17 ++++++ .../service/DefaultGeoLocationService.java | 12 ++++ .../service/DefaultHealthService.java | 58 +++++++++++++++++++ .../healthapp/service/GeoLocationService.java | 6 ++ .../healthapp/service/HealthService.java | 10 ++++ .../src/main/resources/application.properties | 10 ++++ .../DefaultHealthServiceManualTest.java | 55 ++++++++++++++++++ 10 files changed, 235 insertions(+) create mode 100644 persistence-modules/fauna/src/main/java/com/baeldung/healthapp/FaunaClients.java create mode 100644 persistence-modules/fauna/src/main/java/com/baeldung/healthapp/FaunaHealthApplication.java create mode 100644 persistence-modules/fauna/src/main/java/com/baeldung/healthapp/domain/HealthData.java create mode 100644 persistence-modules/fauna/src/main/java/com/baeldung/healthapp/service/DefaultGeoLocationService.java create mode 100644 persistence-modules/fauna/src/main/java/com/baeldung/healthapp/service/DefaultHealthService.java create mode 100644 persistence-modules/fauna/src/main/java/com/baeldung/healthapp/service/GeoLocationService.java create mode 100644 persistence-modules/fauna/src/main/java/com/baeldung/healthapp/service/HealthService.java create mode 100644 persistence-modules/fauna/src/test/java/com/baeldung/healthapp/service/DefaultHealthServiceManualTest.java diff --git a/persistence-modules/fauna/pom.xml b/persistence-modules/fauna/pom.xml index 8c985e0b7c..cd66bf247b 100644 --- a/persistence-modules/fauna/pom.xml +++ b/persistence-modules/fauna/pom.xml @@ -41,6 +41,18 @@ spring-security-test test + + org.springframework.boot + spring-boot-configuration-processor + true + + + + + org.projectlombok + lombok + provided + diff --git a/persistence-modules/fauna/src/main/java/com/baeldung/healthapp/FaunaClients.java b/persistence-modules/fauna/src/main/java/com/baeldung/healthapp/FaunaClients.java new file mode 100644 index 0000000000..c4e1d52b5b --- /dev/null +++ b/persistence-modules/fauna/src/main/java/com/baeldung/healthapp/FaunaClients.java @@ -0,0 +1,42 @@ +package com.baeldung.healthapp; + +import java.net.MalformedURLException; +import java.util.HashMap; +import java.util.Map; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import com.faunadb.client.FaunaClient; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@ConfigurationProperties +@Component +public class FaunaClients { + + private final Map faunaConnections = new HashMap<>(); + private final Map faunaSecrets = new HashMap<>(); + + public FaunaClient getFaunaClient(String region) throws MalformedURLException { + + String faunaUrl = faunaConnections.get(region); + String faunaSecret = faunaSecrets.get(region); + + log.info("Creating Fauna Client for Region:{} with URL:{}", region, faunaUrl); + + return FaunaClient.builder() + .withEndpoint(faunaUrl) + .withSecret(faunaSecret) + .build(); + } + + public Map getFaunaConnections() { + return faunaConnections; + } + + public Map getFaunaSecrets() { + return faunaSecrets; + } +} diff --git a/persistence-modules/fauna/src/main/java/com/baeldung/healthapp/FaunaHealthApplication.java b/persistence-modules/fauna/src/main/java/com/baeldung/healthapp/FaunaHealthApplication.java new file mode 100644 index 0000000000..ac09e4cd36 --- /dev/null +++ b/persistence-modules/fauna/src/main/java/com/baeldung/healthapp/FaunaHealthApplication.java @@ -0,0 +1,13 @@ +package com.baeldung.healthapp; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class FaunaHealthApplication { + + public static void main(String[] args) { + SpringApplication.run(FaunaHealthApplication.class, args); + } + +} diff --git a/persistence-modules/fauna/src/main/java/com/baeldung/healthapp/domain/HealthData.java b/persistence-modules/fauna/src/main/java/com/baeldung/healthapp/domain/HealthData.java new file mode 100644 index 0000000000..9ee320c3d5 --- /dev/null +++ b/persistence-modules/fauna/src/main/java/com/baeldung/healthapp/domain/HealthData.java @@ -0,0 +1,17 @@ +package com.baeldung.healthapp.domain; + +import java.time.ZonedDateTime; + +public record HealthData( + + String userId, + + float temperature, + float pulseRate, + int bpSystolic, + int bpDiastolic, + + double latitude, + double longitude, + ZonedDateTime timestamp) { +} diff --git a/persistence-modules/fauna/src/main/java/com/baeldung/healthapp/service/DefaultGeoLocationService.java b/persistence-modules/fauna/src/main/java/com/baeldung/healthapp/service/DefaultGeoLocationService.java new file mode 100644 index 0000000000..b643714972 --- /dev/null +++ b/persistence-modules/fauna/src/main/java/com/baeldung/healthapp/service/DefaultGeoLocationService.java @@ -0,0 +1,12 @@ +package com.baeldung.healthapp.service; + +import org.springframework.stereotype.Component; + +@Component +public class DefaultGeoLocationService implements GeoLocationService { + + @Override + public String getRegion(double latitude, double longitude) { + return "EU"; + } +} diff --git a/persistence-modules/fauna/src/main/java/com/baeldung/healthapp/service/DefaultHealthService.java b/persistence-modules/fauna/src/main/java/com/baeldung/healthapp/service/DefaultHealthService.java new file mode 100644 index 0000000000..8e44b4b243 --- /dev/null +++ b/persistence-modules/fauna/src/main/java/com/baeldung/healthapp/service/DefaultHealthService.java @@ -0,0 +1,58 @@ +package com.baeldung.healthapp.service; + +import static com.faunadb.client.query.Language.Collection; +import static com.faunadb.client.query.Language.Create; +import static com.faunadb.client.query.Language.Now; +import static com.faunadb.client.query.Language.Obj; +import static com.faunadb.client.query.Language.Value; + +import java.net.MalformedURLException; +import java.util.Map; +import java.util.concurrent.ExecutionException; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.baeldung.healthapp.FaunaClients; +import com.baeldung.healthapp.domain.HealthData; +import com.faunadb.client.FaunaClient; +import com.faunadb.client.types.Value; + +import lombok.extern.slf4j.Slf4j; + +@Component +@Slf4j +public class DefaultHealthService implements HealthService { + + @Autowired + private GeoLocationService geoLocationService; + + @Autowired + private FaunaClients faunaClients; + + @Override + public void process(HealthData healthData) throws MalformedURLException, InterruptedException, ExecutionException { + + String region = geoLocationService.getRegion( // + healthData.latitude(), // + healthData.longitude()); + + FaunaClient faunaClient = faunaClients.getFaunaClient(region); + + Value queryResponse = faunaClient.query( + Create(Collection("healthdata"), + Obj("data", + Obj(Map.of( + "userId", Value(healthData.userId()), + "temperature", Value(healthData.temperature()), + "pulseRate", Value(healthData.pulseRate()), + "bpSystolic", Value(healthData.bpSystolic()), + "bpDiastolic", Value(healthData.bpDiastolic()), + "latitude", Value(healthData.latitude()), + "longitude", Value(healthData.longitude()), + "timestamp", Now())))) + ).get(); + + log.info("Query response received from Fauna: {}", queryResponse); + } +} diff --git a/persistence-modules/fauna/src/main/java/com/baeldung/healthapp/service/GeoLocationService.java b/persistence-modules/fauna/src/main/java/com/baeldung/healthapp/service/GeoLocationService.java new file mode 100644 index 0000000000..43a3204610 --- /dev/null +++ b/persistence-modules/fauna/src/main/java/com/baeldung/healthapp/service/GeoLocationService.java @@ -0,0 +1,6 @@ +package com.baeldung.healthapp.service; + +public interface GeoLocationService { + + String getRegion(double latitude, double longitude); +} diff --git a/persistence-modules/fauna/src/main/java/com/baeldung/healthapp/service/HealthService.java b/persistence-modules/fauna/src/main/java/com/baeldung/healthapp/service/HealthService.java new file mode 100644 index 0000000000..eadf12cc08 --- /dev/null +++ b/persistence-modules/fauna/src/main/java/com/baeldung/healthapp/service/HealthService.java @@ -0,0 +1,10 @@ +package com.baeldung.healthapp.service; + +import java.net.MalformedURLException; +import java.util.concurrent.ExecutionException; + +import com.baeldung.healthapp.domain.HealthData; + +public interface HealthService { + void process(HealthData healthData) throws MalformedURLException, InterruptedException, ExecutionException; +} diff --git a/persistence-modules/fauna/src/main/resources/application.properties b/persistence-modules/fauna/src/main/resources/application.properties index e69de29bb2..d17d80c13b 100644 --- a/persistence-modules/fauna/src/main/resources/application.properties +++ b/persistence-modules/fauna/src/main/resources/application.properties @@ -0,0 +1,10 @@ +# Fauna Blog Service +fauna.region=EU +fauna.secret= + +# Fauna Health App +fauna-connections.EU=https://db.eu.fauna.com/ +fauna-secrets.EU=fnAEsvJPtDAA0MyJZzrPNfjYGN49aiJe-7QfPdSo + +fauna-connections.US=https://db.us.fauna.com/ +fauna-secrets.US=fnAEsvKMCyAAQnx8-T_lWbhH91HOH_9374GpD4en \ No newline at end of file diff --git a/persistence-modules/fauna/src/test/java/com/baeldung/healthapp/service/DefaultHealthServiceManualTest.java b/persistence-modules/fauna/src/test/java/com/baeldung/healthapp/service/DefaultHealthServiceManualTest.java new file mode 100644 index 0000000000..f77eb623b6 --- /dev/null +++ b/persistence-modules/fauna/src/test/java/com/baeldung/healthapp/service/DefaultHealthServiceManualTest.java @@ -0,0 +1,55 @@ +package com.baeldung.healthapp.service; + +import static org.mockito.Mockito.when; + +import java.net.MalformedURLException; +import java.time.ZonedDateTime; +import java.util.concurrent.ExecutionException; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; + +import com.baeldung.healthapp.FaunaHealthApplication; +import com.baeldung.healthapp.domain.HealthData; + +@SpringBootTest(classes = FaunaHealthApplication.class) +class DefaultHealthServiceManualTest { + + @Autowired + private DefaultHealthService defaultHealthService; + + @MockBean + private GeoLocationService geoLocationService; + + @Test + void givenEURegion_whenProcess_thenRequestSentToEURegion() throws MalformedURLException, InterruptedException, ExecutionException { + + HealthData healthData = new HealthData("user-1-eu", // + 37.5f, // + 99f, // + 120, 80, // + 51.50, -0.07, // + ZonedDateTime.now()); + + when(geoLocationService.getRegion(51.50, -0.07)).thenReturn("EU"); + + defaultHealthService.process(healthData); + } + + @Test + void givenUSRegion_whenProcess_thenRequestSentToUSRegion() throws MalformedURLException, InterruptedException, ExecutionException { + + HealthData healthData = new HealthData("user-1-us", // + 38.0f, // + 100f, // + 115, 85, // + 40.75, -74.30, // + ZonedDateTime.now()); + + when(geoLocationService.getRegion(40.75, -74.30)).thenReturn("US"); + + defaultHealthService.process(healthData); + } +} From d93e6d3bc0fa2d3eb12db5122422137ebc9b30b3 Mon Sep 17 00:00:00 2001 From: Dhawal Kapil Date: Sun, 31 Jul 2022 22:07:20 +0530 Subject: [PATCH 2/3] BAEL-5230 Removed secrets from the codebase --- .../fauna/src/main/resources/application.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/persistence-modules/fauna/src/main/resources/application.properties b/persistence-modules/fauna/src/main/resources/application.properties index d17d80c13b..0f50dfa8b3 100644 --- a/persistence-modules/fauna/src/main/resources/application.properties +++ b/persistence-modules/fauna/src/main/resources/application.properties @@ -4,7 +4,7 @@ fauna.secret= # Fauna Health App fauna-connections.EU=https://db.eu.fauna.com/ -fauna-secrets.EU=fnAEsvJPtDAA0MyJZzrPNfjYGN49aiJe-7QfPdSo +fauna-secrets.EU=eu-secret fauna-connections.US=https://db.us.fauna.com/ -fauna-secrets.US=fnAEsvKMCyAAQnx8-T_lWbhH91HOH_9374GpD4en \ No newline at end of file +fauna-secrets.US=us-secret \ No newline at end of file From 25c755bb68936e4439369ffa893ce8ef535e4d90 Mon Sep 17 00:00:00 2001 From: Dhawal Kapil Date: Sun, 31 Jul 2022 23:23:37 +0530 Subject: [PATCH 3/3] JAVA-13630 Updated code for Mockito - Using Spies Article --- .../spy/MockitoMisusingMockOrSpyUnitTest.java | 30 +++++++++++++++ .../mockito/spy/MockitoMisusingUnitTest.java | 38 ------------------- .../mockito/spy/MockitoSpyUnitTest.java | 29 +++++++------- 3 files changed, 45 insertions(+), 52 deletions(-) create mode 100644 testing-modules/mockito-simple/src/test/java/com/baeldung/mockito/spy/MockitoMisusingMockOrSpyUnitTest.java delete mode 100644 testing-modules/mockito-simple/src/test/java/com/baeldung/mockito/spy/MockitoMisusingUnitTest.java diff --git a/testing-modules/mockito-simple/src/test/java/com/baeldung/mockito/spy/MockitoMisusingMockOrSpyUnitTest.java b/testing-modules/mockito-simple/src/test/java/com/baeldung/mockito/spy/MockitoMisusingMockOrSpyUnitTest.java new file mode 100644 index 0000000000..b3f470427a --- /dev/null +++ b/testing-modules/mockito-simple/src/test/java/com/baeldung/mockito/spy/MockitoMisusingMockOrSpyUnitTest.java @@ -0,0 +1,30 @@ +package com.baeldung.mockito.spy; + +import static org.assertj.core.api.Assertions.assertThatNoException; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; +import org.mockito.Mockito; +import org.mockito.exceptions.misusing.NotAMockException; + +public class MockitoMisusingMockOrSpyUnitTest { + + @Test + public void givenNotASpy_whenDoReturn_thenThrowNotAMock() { + List list = new ArrayList(); + + assertThatThrownBy(() -> Mockito.doReturn(100).when(list).size()) + .isInstanceOf(NotAMockException.class) + .hasMessageContaining("Argument passed to when() is not a mock!"); + } + + @Test + public void givenASpy_whenDoReturn_thenNoError() { + final List spyList = Mockito.spy(new ArrayList<>()); + + assertThatNoException().isThrownBy(() -> Mockito.doReturn(100).when(spyList).size()); + } +} diff --git a/testing-modules/mockito-simple/src/test/java/com/baeldung/mockito/spy/MockitoMisusingUnitTest.java b/testing-modules/mockito-simple/src/test/java/com/baeldung/mockito/spy/MockitoMisusingUnitTest.java deleted file mode 100644 index ea12061fc6..0000000000 --- a/testing-modules/mockito-simple/src/test/java/com/baeldung/mockito/spy/MockitoMisusingUnitTest.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.baeldung.mockito.spy; - -import org.junit.After; -import org.junit.Test; -import org.mockito.Mockito; -import org.mockito.exceptions.misusing.NotAMockException; -import org.mockito.internal.progress.ThreadSafeMockingProgress; - -import java.util.ArrayList; -import java.util.List; - -import static org.hamcrest.CoreMatchers.containsString; -import static org.junit.Assert.assertThat; -import static org.junit.jupiter.api.Assertions.fail; - -public class MockitoMisusingUnitTest { - - @After - public void tearDown() { - ThreadSafeMockingProgress.mockingProgress().reset(); - } - - @Test - public void givenNotASpy_whenDoReturn_thenThrowNotAMock() { - try { - List list = new ArrayList(); - - Mockito.doReturn(100, Mockito.withSettings().lenient()) - .when(list) - .size(); - - fail("Should have thrown a NotAMockException because 'list' is not a mock!"); - } catch (NotAMockException e) { - assertThat(e.getMessage(), containsString("Argument passed to when() is not a mock!")); - } - } - -} diff --git a/testing-modules/mockito-simple/src/test/java/com/baeldung/mockito/spy/MockitoSpyUnitTest.java b/testing-modules/mockito-simple/src/test/java/com/baeldung/mockito/spy/MockitoSpyUnitTest.java index d4696e482b..28ca0c327b 100644 --- a/testing-modules/mockito-simple/src/test/java/com/baeldung/mockito/spy/MockitoSpyUnitTest.java +++ b/testing-modules/mockito-simple/src/test/java/com/baeldung/mockito/spy/MockitoSpyUnitTest.java @@ -1,22 +1,20 @@ package com.baeldung.mockito.spy; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertEquals; + +import java.util.ArrayList; +import java.util.List; + import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; import org.mockito.Spy; import org.mockito.junit.MockitoJUnitRunner; -import java.util.ArrayList; -import java.util.List; - -import static org.junit.Assert.assertEquals; - @RunWith(MockitoJUnitRunner.class) public class MockitoSpyUnitTest { - @Spy - private List aSpyList = new ArrayList(); - @Test public void whenSpyingOnList_thenCorrect() { final List list = new ArrayList(); @@ -28,9 +26,12 @@ public class MockitoSpyUnitTest { Mockito.verify(spyList).add("one"); Mockito.verify(spyList).add("two"); - assertEquals(2, spyList.size()); + assertThat(spyList).hasSize(2); } + @Spy + private List aSpyList = new ArrayList(); + @Test public void whenUsingTheSpyAnnotation_thenObjectIsSpied() { aSpyList.add("one"); @@ -39,7 +40,7 @@ public class MockitoSpyUnitTest { Mockito.verify(aSpyList).add("one"); Mockito.verify(aSpyList).add("two"); - assertEquals(2, aSpyList.size()); + assertThat(aSpyList).hasSize(2); } @Test @@ -50,7 +51,7 @@ public class MockitoSpyUnitTest { assertEquals(0, spyList.size()); Mockito.doReturn(100).when(spyList).size(); - assertEquals(100, spyList.size()); + assertThat(spyList).hasSize(100); } @Test @@ -60,17 +61,17 @@ public class MockitoSpyUnitTest { mockedList.add("one"); Mockito.verify(mockedList).add("one"); - assertEquals(0, mockedList.size()); + assertThat(mockedList).hasSize(0); } @Test public void whenCreateSpy_thenCreate() { - final List spyList = Mockito.spy(new ArrayList()); + final List spyList = Mockito.spy(new ArrayList<>()); spyList.add("one"); Mockito.verify(spyList).add("one"); - assertEquals(1, spyList.size()); + assertThat(spyList).hasSize(1); } }