diff --git a/account-service/src/test/java/pl/piomin/microservices/advanced/account/api/AccountControllerTest.java b/account-service/src/test/java/pl/piomin/microservices/advanced/account/api/AccountControllerTest.java new file mode 100644 index 0000000..6841cf5 --- /dev/null +++ b/account-service/src/test/java/pl/piomin/microservices/advanced/account/api/AccountControllerTest.java @@ -0,0 +1,212 @@ + +package pl.piomin.microservices.advanced.account.api; + +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; +import org.testcontainers.containers.MongoDBContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; +import pl.piomin.microservices.advanced.account.model.Account; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, + properties = {"spring.cloud.discovery.enabled=false"}) +@Testcontainers +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +public class AccountControllerTest { + + @Container + static MongoDBContainer mongoDBContainer = new MongoDBContainer("mongo:8.0"); + + @DynamicPropertySource + static void registerMongoProperties(DynamicPropertyRegistry registry) { + registry.add("spring.data.mongodb.uri", () -> mongoDBContainer.getConnectionString() + "/test"); + } + + @Autowired + TestRestTemplate restTemplate; + + private static String accountId; + private static final String ACCOUNT_NUMBER = "ACC12345678"; + private static final String CUSTOMER_ID = "CUST12345"; + + @Test + @Order(1) + public void testAddAccount() { + Account account = new Account(); + account.setNumber(ACCOUNT_NUMBER); + account.setCustomerId(CUSTOMER_ID); + account.setBalance(5000); + + ResponseEntity response = restTemplate.postForEntity("/accounts", account, Account.class); + assertEquals(HttpStatus.OK, response.getStatusCode()); + Account created = response.getBody(); + assertNotNull(created); + assertNotNull(created.getId()); + assertEquals(ACCOUNT_NUMBER, created.getNumber()); + assertEquals(CUSTOMER_ID, created.getCustomerId()); + assertEquals(5000, created.getBalance()); + accountId = created.getId(); + } + + @Test + @Order(2) + public void testFindByNumber() { + ResponseEntity response = restTemplate.getForEntity("/accounts/{number}", Account.class, ACCOUNT_NUMBER); + assertEquals(HttpStatus.OK, response.getStatusCode()); + Account found = response.getBody(); + assertNotNull(found); + assertEquals(accountId, found.getId()); + assertEquals(ACCOUNT_NUMBER, found.getNumber()); + assertEquals(CUSTOMER_ID, found.getCustomerId()); + } + + @Test + @Order(3) + public void testFindByCustomer() { + ResponseEntity> response = restTemplate.exchange( + "/accounts/customer/{customerId}", + HttpMethod.GET, + null, + new ParameterizedTypeReference>() {}, + CUSTOMER_ID); + assertEquals(HttpStatus.OK, response.getStatusCode()); + List list = response.getBody(); + assertNotNull(list); + assertFalse(list.isEmpty()); + assertEquals(1, list.size()); + assertEquals(accountId, list.get(0).getId()); + assertEquals(ACCOUNT_NUMBER, list.get(0).getNumber()); + } + + @Test + @Order(4) + public void testFindAll() { + ResponseEntity> response = restTemplate.exchange( + "/accounts", + HttpMethod.GET, + null, + new ParameterizedTypeReference>() {}); + assertEquals(HttpStatus.OK, response.getStatusCode()); + assertNotNull(response.getBody()); + assertFalse(response.getBody().isEmpty()); + } + + @Test + @Order(5) + public void testUpdateAccount() { + ResponseEntity getResp = restTemplate.getForEntity("/accounts/{number}", Account.class, ACCOUNT_NUMBER); + Account account = getResp.getBody(); + assertNotNull(account); + int newBalance = 7500; + account.setBalance(newBalance); + restTemplate.put("/accounts", account); + ResponseEntity updatedResp = restTemplate.getForEntity("/accounts/{number}", Account.class, ACCOUNT_NUMBER); + assertEquals(newBalance, updatedResp.getBody().getBalance()); + assertEquals(accountId, updatedResp.getBody().getId()); + } +} + +package pl.piomin.microservices.advanced.account.api; + +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.containers.MongoDBContainer; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; +import pl.piomin.microservices.advanced.account.model.Account; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, + properties = {"spring.cloud.discovery.enabled=false"}) +@Testcontainers +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +public class AccountControllerTest { + + @Container + static MongoDBContainer mongoDB = new MongoDBContainer("mongo:8.0"); + + @DynamicPropertySource + static void setProps(DynamicPropertyRegistry registry) { + registry.add("spring.data.mongodb.uri", () -> mongoDB.getConnectionString() + "/test"); + } + + @Autowired + TestRestTemplate restTemplate; + + private static String accountId; + private static final String NUMBER = "ACC12345678"; + private static final String CUSTOMER = "CUST12345"; + + @Test @Order(1) + public void testAddAccount() { + Account a = new Account(); + a.setNumber(NUMBER); + a.setCustomerId(CUSTOMER); + a.setBalance(5000); + ResponseEntity r = restTemplate.postForEntity("/accounts", a, Account.class); + assertEquals(HttpStatus.OK, r.getStatusCode()); + assertNotNull(r.getBody().getId()); + accountId = r.getBody().getId(); + assertEquals(NUMBER, r.getBody().getNumber()); + } + + @Test @Order(2) + public void testFindByNumber() { + ResponseEntity r = restTemplate.getForEntity("/accounts/{number}", Account.class, NUMBER); + assertEquals(HttpStatus.OK, r.getStatusCode()); + assertEquals(accountId, r.getBody().getId()); + } + + @Test @Order(3) + public void testFindByCustomer() { + ResponseEntity> r = restTemplate.exchange( + "/accounts/customer/{cust}", HttpMethod.GET, null, + new ParameterizedTypeReference>() {}, CUSTOMER); + assertFalse(r.getBody().isEmpty()); + } + + @Test @Order(4) + public void testFindAll() { + ResponseEntity> r = restTemplate.exchange( + "/accounts", HttpMethod.GET, null, + new ParameterizedTypeReference>() {}); + assertTrue(r.getBody().size() >= 1); + } + + @Test @Order(5) + public void testUpdateAccount() { + Account a = restTemplate.getForEntity("/accounts/{number}", Account.class, NUMBER).getBody(); + a.setBalance(7500); + restTemplate.put("/accounts", a); + assertEquals(7500, restTemplate.getForEntity("/accounts/{number}", Account.class, NUMBER).getBody().getBalance()); + } +} diff --git a/account-service/src/test/java/pl/piomin/microservices/advanced/account/config/AccountContainersConfiguration.java b/account-service/src/test/java/pl/piomin/microservices/advanced/account/config/AccountContainersConfiguration.java index c12144b..a069a07 100644 --- a/account-service/src/test/java/pl/piomin/microservices/advanced/account/config/AccountContainersConfiguration.java +++ b/account-service/src/test/java/pl/piomin/microservices/advanced/account/config/AccountContainersConfiguration.java @@ -1,18 +1,31 @@ + package pl.piomin.microservices.advanced.account.config; import org.springframework.boot.test.context.TestConfiguration; -import org.springframework.boot.testcontainers.service.connection.ServiceConnection; import org.springframework.context.annotation.Bean; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; import org.testcontainers.containers.MongoDBContainer; -import org.testcontainers.utility.DockerImageName; +import org.testcontainers.junit.jupiter.Container; -@TestConfiguration(proxyBeanMethods = false) +@TestConfiguration public class AccountContainersConfiguration { - @Bean - @ServiceConnection - public MongoDBContainer mongodbContainer() { - return new MongoDBContainer(DockerImageName.parse("mongo:8.0")); + @Container + private static final MongoDBContainer mongoDBContainer = new MongoDBContainer("mongo:8.0"); + + static { + mongoDBContainer.start(); } + @DynamicPropertySource + static void setProperties(DynamicPropertyRegistry registry) { + String uri = mongoDBContainer.getConnectionString() + "/test"; + registry.add("spring.data.mongodb.uri", () -> uri); + } + + @Bean + public MongoDBContainer mongoDbContainer() { + return mongoDBContainer; + } } diff --git a/account-service/src/test/java/pl/piomin/microservices/advanced/account/repository/AccountRepositoryTest.java b/account-service/src/test/java/pl/piomin/microservices/advanced/account/repository/AccountRepositoryTest.java index def9588..a2a4806 100644 --- a/account-service/src/test/java/pl/piomin/microservices/advanced/account/repository/AccountRepositoryTest.java +++ b/account-service/src/test/java/pl/piomin/microservices/advanced/account/repository/AccountRepositoryTest.java @@ -1,68 +1,128 @@ -package pl.piomin.microservices.advanced.account.repository; - -import org.junit.jupiter.api.MethodOrderer; -import org.junit.jupiter.api.Order; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestMethodOrder; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest; -import org.springframework.test.context.DynamicPropertyRegistry; -import org.springframework.test.context.DynamicPropertySource; -import org.testcontainers.containers.MongoDBContainer; -import org.testcontainers.junit.jupiter.Container; -import org.testcontainers.junit.jupiter.Testcontainers; -import pl.piomin.microservices.advanced.account.model.Account; - -import java.util.Optional; - -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; - -@DataMongoTest -@Testcontainers -@TestMethodOrder(MethodOrderer.OrderAnnotation.class) -public class AccountRepositoryTest { - - @Container - static MongoDBContainer mongoDBContainer = new MongoDBContainer("mongo:8.0"); - - @DynamicPropertySource - static void registerMongoProperties(DynamicPropertyRegistry registry) { - String uri = mongoDBContainer.getConnectionString() + "/test"; - registry.add("spring.data.mongodb.uri", () -> uri); - } - - static String id; - - @Autowired - AccountRepository repository; - - @Test - @Order(1) - public void testAddAccount() { - Account a = new Account(); - a.setNumber("12345678909"); - a.setBalance(1232); - a.setCustomerId("234353464576586464"); - a = repository.save(a); - assertNotNull(a); - assertNotNull(a.getId()); - id = a.getId(); - } - - @Test - @Order(2) - public void testFindAccount() { - Optional optAcc = repository.findById(id); - assertTrue(optAcc.isPresent()); - } - - @Test - @Order(2) - public void testFindAccountByNumber() { - Account a = repository.findByNumber("12345678909"); - assertNotNull(a); - assertNotNull(a.getId()); - } - -} + +package pl.piomin.microservices.advanced.account.repository; + +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.data.mongo.DataMongoTest; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; +import org.testcontainers.containers.MongoDBContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; +import pl.piomin.microservices.advanced.account.model.Account; + +import java.util.Optional; +import java.util.List; +import java.util.UUID; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@DataMongoTest +@Testcontainers +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +public class AccountRepositoryTest { + + @Container + static MongoDBContainer mongoDBContainer = new MongoDBContainer("mongo:8.0"); + + @DynamicPropertySource + static void registerMongoProperties(DynamicPropertyRegistry registry) { + String uri = mongoDBContainer.getConnectionString() + "/test"; + registry.add("spring.data.mongodb.uri", () -> uri); + } + + static String id; + static final String ACCOUNT_NUMBER = "12345678909"; + static final String CUSTOMER_ID = "234353464576586464"; + + @Autowired + AccountRepository repository; + + @Test + @Order(1) + public void testAddAccount() { + Account a = new Account(); + a.setNumber(ACCOUNT_NUMBER); + a.setBalance(1232); + a.setCustomerId(CUSTOMER_ID); + a = repository.save(a); + assertNotNull(a); + assertNotNull(a.getId()); + assertEquals(1232, a.getBalance()); + assertEquals(ACCOUNT_NUMBER, a.getNumber()); + assertEquals(CUSTOMER_ID, a.getCustomerId()); + id = a.getId(); + } + + @Test + @Order(2) + public void testFindAccount() { + Optional optAcc = repository.findById(id); + assertTrue(optAcc.isPresent()); + Account account = optAcc.get(); + assertEquals(id, account.getId()); + assertEquals(ACCOUNT_NUMBER, account.getNumber()); + assertEquals(CUSTOMER_ID, account.getCustomerId()); + assertEquals(1232, account.getBalance()); + } + + @Test + @Order(2) + public void testFindAccountByNumber() { + Account a = repository.findByNumber(ACCOUNT_NUMBER); + assertNotNull(a); + assertNotNull(a.getId()); + assertEquals(id, a.getId()); + assertEquals(CUSTOMER_ID, a.getCustomerId()); + } + + @Test + @Order(3) + public void testFindAccountsByCustomerId() { + List accounts = repository.findByCustomerId(CUSTOMER_ID); + assertNotNull(accounts); + assertFalse(accounts.isEmpty()); + assertEquals(1, accounts.size()); + assertEquals(id, accounts.get(0).getId()); + assertEquals(ACCOUNT_NUMBER, accounts.get(0).getNumber()); + } + + @Test + @Order(4) + public void testUpdateAccountBalance() { + Optional optAcc = repository.findById(id); + assertTrue(optAcc.isPresent()); + Account account = optAcc.get(); + int newBalance = 2500; + account.setBalance(newBalance); + Account updated = repository.save(account); + assertEquals(newBalance, updated.getBalance()); + assertEquals(id, updated.getId()); + assertEquals(ACCOUNT_NUMBER, updated.getNumber()); + } + + @Test + @Order(5) + public void testFindAllAccounts() { + List accounts = repository.findAll(); + assertNotNull(accounts); + assertFalse(accounts.isEmpty()); + } + + @Test + @Order(6) + public void testFindNonExistentAccount() { + String randomId = UUID.randomUUID().toString(); + Optional optAccount = repository.findById(randomId); + assertFalse(optAccount.isPresent()); + Account nonExistentAccount = repository.findByNumber("non-existent-number"); + assertEquals(null, nonExistentAccount); + } + +} diff --git a/customer-service/src/test/java/pl/piomin/microservices/advanced/customer/CustomerControllerTests.java b/customer-service/src/test/java/pl/piomin/microservices/advanced/customer/CustomerControllerTests.java index e552bc8..be6ee03 100644 --- a/customer-service/src/test/java/pl/piomin/microservices/advanced/customer/CustomerControllerTests.java +++ b/customer-service/src/test/java/pl/piomin/microservices/advanced/customer/CustomerControllerTests.java @@ -27,6 +27,8 @@ import static io.specto.hoverfly.junit.dsl.matchers.HoverflyMatchers.startsWith; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, properties = { @@ -46,11 +48,13 @@ static void registerMongoProperties(DynamicPropertyRegistry registry) { registry.add("spring.data.mongodb.uri", () -> uri); } - static String id; - @Autowired TestRestTemplate template; + static String id; + static final String CUSTOMER_PESSEL = "1234567890"; + static final String CUSTOMER_NAME = "Jan Testowy"; + @Test @Order(1) public void addCustomerTest() { @@ -58,19 +62,25 @@ public void addCustomerTest() { c.setType(CustomerType.INDIVIDUAL); c.setPesel("1234567890"); c.setName("Jan Testowy"); - c = template.postForObject("/customers", c, Customer.class); + Customer created = template.postForObject("/customers", c, Customer.class); + assertNotNull(created); + assertNotNull(created.getId()); + assertEquals(CUSTOMER_PESSEL, created.getPesel()); + assertEquals(CUSTOMER_NAME, created.getName()); + assertEquals(CustomerType.INDIVIDUAL, created.getType()); + id = created.getId(); } -// @Test -// @Order(2) + @Test + @Order(2) public void findCustomerWithAccounts(Hoverfly hoverfly) { hoverfly.simulate( dsl(service("http://account-service") .get(startsWith("/accounts/customer")) .willReturn(success("[{\"id\":\"1\",\"number\":\"1234567890\"}]", "application/json")))); - Customer c = template.getForObject("/customers/pesel/{pesel}", Customer.class, "1234567890"); - Customer cc = template.getForObject("/customers/{id}", Customer.class, c.getId()); + Customer c = template.getForObject("/customers/pesel/{pesel}", Customer.class, CUSTOMER_PESSEL); + Customer cc = template.getForObject("/customers/{id}", Customer.class, id); assertNotNull(cc); assertTrue(cc.getAccounts().size() > 0); } diff --git a/customer-service/src/test/java/pl/piomin/microservices/advanced/customer/CustomerRepositoryTests.java b/customer-service/src/test/java/pl/piomin/microservices/advanced/customer/CustomerRepositoryTests.java index 29b0d90..9502cef 100644 --- a/customer-service/src/test/java/pl/piomin/microservices/advanced/customer/CustomerRepositoryTests.java +++ b/customer-service/src/test/java/pl/piomin/microservices/advanced/customer/CustomerRepositoryTests.java @@ -1,3 +1,4 @@ + package pl.piomin.microservices.advanced.customer; import org.junit.jupiter.api.MethodOrderer; @@ -16,9 +17,13 @@ import pl.piomin.microservices.advanced.customer.repository.CustomerRepository; import java.util.Optional; +import java.util.List; +import java.util.UUID; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; @DataMongoTest @Testcontainers @@ -35,6 +40,8 @@ static void registerMongoProperties(DynamicPropertyRegistry registry) { } static String id; + static final String CUSTOMER_NAME = "Test1"; + static final String CUSTOMER_PESEL = "1234567890"; @Autowired CustomerRepository repository; @@ -43,13 +50,16 @@ static void registerMongoProperties(DynamicPropertyRegistry registry) { @Order(1) public void testAddCustomer() { Customer c = new Customer(); - c.setName("Test1"); - c.setPesel("1234567890"); + c.setName(CUSTOMER_NAME); + c.setPesel(CUSTOMER_PESEL); c.setType(CustomerType.INDIVIDUAL); c = repository.save(c); assertNotNull(c); assertNotNull(c.getId()); id = c.getId(); + assertEquals(CUSTOMER_NAME, c.getName()); + assertEquals(CUSTOMER_PESEL, c.getPesel()); + assertEquals(CustomerType.INDIVIDUAL, c.getType()); } @Test @@ -57,14 +67,72 @@ public void testAddCustomer() { public void testFindCustomer() { Optional optCus = repository.findById(id); assertTrue(optCus.isPresent()); + Customer customer = optCus.get(); + assertEquals(id, customer.getId()); + assertEquals(CUSTOMER_NAME, customer.getName()); + assertEquals(CUSTOMER_PESEL, customer.getPesel()); + assertEquals(CustomerType.INDIVIDUAL, customer.getType()); } @Test @Order(2) public void testFindCustomerByPesel() { - Customer c = repository.findByPesel("1234567890"); + Customer c = repository.findByPesel(CUSTOMER_PESEL); assertNotNull(c); assertNotNull(c.getId()); + assertEquals(id, c.getId()); + assertEquals(CUSTOMER_NAME, c.getName()); + assertEquals(CustomerType.INDIVIDUAL, c.getType()); + } + + @Test + @Order(3) + public void testUpdateCustomer() { + Optional optCus = repository.findById(id); + assertTrue(optCus.isPresent()); + Customer customer = optCus.get(); + // Update name + String newName = "Updated Name"; + customer.setName(newName); + Customer updated = repository.save(customer); + assertEquals(newName, updated.getName()); + assertEquals(id, updated.getId()); + assertEquals(CUSTOMER_PESEL, updated.getPesel()); + assertEquals(CustomerType.INDIVIDUAL, updated.getType()); + } + + @Test + @Order(4) + public void testFindAllCustomers() { + List customers = repository.findAll(); + assertNotNull(customers); + assertFalse(customers.isEmpty()); + assertTrue(customers.size() >= 1); + } + + @Test + @Order(5) + public void testAddCorporateCustomer() { + Customer c = new Customer(); + c.setName("Corporate Inc."); + c.setPesel("9876543210"); + c.setType(CustomerType.CORPORATE); + c = repository.save(c); + assertNotNull(c); + assertNotNull(c.getId()); + assertEquals("Corporate Inc.", c.getName()); + assertEquals("9876543210", c.getPesel()); + assertEquals(CustomerType.CORPORATE, c.getType()); + } + + @Test + @Order(6) + public void testFindNonExistentCustomer() { + String randomId = UUID.randomUUID().toString(); + Optional optCustomer = repository.findById(randomId); + assertFalse(optCustomer.isPresent()); + Customer nonExistentCustomer = repository.findByPesel("non-existent-pesel"); + assertEquals(null, nonExistentCustomer); } } diff --git a/customer-service/src/test/java/pl/piomin/microservices/advanced/customer/config/CustomerContainersConfiguration.java b/customer-service/src/test/java/pl/piomin/microservices/advanced/customer/config/CustomerContainersConfiguration.java new file mode 100644 index 0000000..211ee5e --- /dev/null +++ b/customer-service/src/test/java/pl/piomin/microservices/advanced/customer/config/CustomerContainersConfiguration.java @@ -0,0 +1,58 @@ +package pl.piomin.microservices.advanced.customer.config; + +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; +import org.testcontainers.containers.MongoDBContainer; +import org.testcontainers.junit.jupiter.Container; + +@TestConfiguration +public class CustomerContainersConfiguration { + + @Container + private static final MongoDBContainer mongoDBContainer = new MongoDBContainer("mongo:8.0"); + + static { + mongoDBContainer.start(); + } + + @DynamicPropertySource + static void setProperties(DynamicPropertyRegistry registry) { + String uri = mongoDBContainer.getConnectionString() + "/test"; + registry.add("spring.data.mongodb.uri", () -> uri); + } + + @Bean + public MongoDBContainer mongoDbContainer() { + return mongoDBContainer; + } +} + +package pl.piomin.microservices.advanced.customer.config; + +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; +import org.testcontainers.containers.MongoDBContainer; +import org.testcontainers.junit.jupiter.Container; + +@TestConfiguration +public class CustomerContainersConfiguration { + + @Container + private static final MongoDBContainer mongoDBContainer = new MongoDBContainer("mongo:8.0"); + + static { mongoDBContainer.start(); } + + @DynamicPropertySource + static void setProperties(DynamicPropertyRegistry registry) { + registry.add("spring.data.mongodb.uri", () -> mongoDBContainer.getConnectionString() + "/test"); + } + + @Bean + public MongoDBContainer mongoDbContainer() { + return mongoDBContainer; + } +} \ No newline at end of file diff --git a/integration-tests/src/test/java/pl/piomin/microservices/advanced/integration/ServiceIntegrationTests.java b/integration-tests/src/test/java/pl/piomin/microservices/advanced/integration/ServiceIntegrationTests.java new file mode 100644 index 0000000..81bd12e --- /dev/null +++ b/integration-tests/src/test/java/pl/piomin/microservices/advanced/integration/ServiceIntegrationTests.java @@ -0,0 +1,104 @@ + +package pl.piomin.microservices.advanced.integration; + +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.context.annotation.ContextConfiguration; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.testcontainers.junit.jupiter.Testcontainers; + +import java.util.HashMap; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.*; + +@SpringBootTest(classes = TestApplication.class, webEnvironment = WebEnvironment.RANDOM_PORT) +@ContextConfiguration(classes = { + pl.piomin.microservices.advanced.account.config.AccountContainersConfiguration.class, + pl.piomin.microservices.advanced.customer.config.CustomerContainersConfiguration.class, + pl.piomin.microservices.advanced.product.config.ProductContainersConfiguration.class +}) +@Testcontainers +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +public class ServiceIntegrationTests { + + @Autowired + private TestRestTemplate restTemplate; + + private static String accountId; + private static String customerId; + private static String productId; + + @Test + @Order(1) + void testAccountCreation() { + Map payload = new HashMap<>(); + payload.put("name", "Test Account"); + ResponseEntity response = restTemplate.postForEntity("/accounts", payload, Map.class); + assertEquals(HttpStatus.OK, response.getStatusCode()); + Map body = response.getBody(); + assertNotNull(body); + assertNotNull(body.get("id")); + accountId = body.get("id").toString(); + } + + @Test + @Order(2) + void testCustomerCreation() { + Map payload = new HashMap<>(); + payload.put("firstName", "John"); + payload.put("lastName", "Doe"); + ResponseEntity response = restTemplate.postForEntity("/customers", payload, Map.class); + assertEquals(HttpStatus.OK, response.getStatusCode()); + Map body = response.getBody(); + assertNotNull(body); + assertNotNull(body.get("id")); + customerId = body.get("id").toString(); + } + + @Test + @Order(3) + void testProductCreation() { + Map payload = new HashMap<>(); + payload.put("name", "Test Product"); + payload.put("accountId", accountId); + payload.put("customerId", customerId); + ResponseEntity response = restTemplate.postForEntity("/products", payload, Map.class); + assertEquals(HttpStatus.OK, response.getStatusCode()); + Map body = response.getBody(); + assertNotNull(body); + assertNotNull(body.get("id")); + productId = body.get("id").toString(); + } + + @Test + @Order(4) + void testServiceToServiceFlow() { + ResponseEntity response = restTemplate.getForEntity("/products/{id}", Map.class, productId); + assertEquals(HttpStatus.OK, response.getStatusCode()); + Map product = response.getBody(); + assertNotNull(product); + assertEquals("Test Product", product.get("name")); + // Verify that customer details are included + Map customer = (Map) product.get("customer"); + assertNotNull(customer); + assertEquals("John", customer.get("firstName")); + assertEquals("Doe", customer.get("lastName")); + } + + @Test + @Order(5) + void testFailureScenario() { + String randomId = "nonexistent-id"; + ResponseEntity response = restTemplate.getForEntity("/products/{id}", Map.class, randomId); + assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode()); + assertTrue(response.getBody() == null || response.getBody().isEmpty()); + } +} diff --git a/product-service/src/test/java/pl/piomin/microservices/advanced/product/ProductRepositoryTests.java b/product-service/src/test/java/pl/piomin/microservices/advanced/product/ProductRepositoryTests.java index 3fe1cce..018d470 100644 --- a/product-service/src/test/java/pl/piomin/microservices/advanced/product/ProductRepositoryTests.java +++ b/product-service/src/test/java/pl/piomin/microservices/advanced/product/ProductRepositoryTests.java @@ -1,3 +1,4 @@ + package pl.piomin.microservices.advanced.product; import org.junit.jupiter.api.MethodOrderer; @@ -17,9 +18,14 @@ import java.time.LocalDate; import java.util.Optional; +import java.util.List; +import java.util.UUID; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; @DataMongoTest @Testcontainers @@ -37,6 +43,10 @@ static void registerMongoProperties(DynamicPropertyRegistry registry) { static String id; + static final String ACCOUNT_ID = "123"; + static final String CUSTOMER_ID = "123"; + static final int INITIAL_BALANCE = 10000; + @Autowired ProductRepository repository; @@ -44,14 +54,19 @@ static void registerMongoProperties(DynamicPropertyRegistry registry) { @Order(1) public void testAddProduct() { Product p = new Product(); - p.setAccountId("123"); - p.setCustomerId("123"); + p.setAccountId(ACCOUNT_ID); + p.setCustomerId(CUSTOMER_ID); p.setType(ProductType.CREDIT); - p.setBalance(10000); + p.setBalance(INITIAL_BALANCE); p.setDateOfStart(LocalDate.now()); p = repository.save(p); assertNotNull(p); assertNotNull(p.getId()); + assertEquals(ACCOUNT_ID, p.getAccountId()); + assertEquals(CUSTOMER_ID, p.getCustomerId()); + assertEquals(ProductType.CREDIT, p.getType()); + assertEquals(INITIAL_BALANCE, p.getBalance()); + assertNotNull(p.getDateOfStart()); id = p.getId(); } @@ -60,13 +75,74 @@ public void testAddProduct() { public void testFindProduct() { Optional optCus = repository.findById(id); assertTrue(optCus.isPresent()); + Product product = optCus.get(); + assertEquals(id, product.getId()); + assertEquals(ACCOUNT_ID, product.getAccountId()); + assertEquals(CUSTOMER_ID, product.getCustomerId()); + assertEquals(ProductType.CREDIT, product.getType()); + assertEquals(INITIAL_BALANCE, product.getBalance()); } @Test @Order(2) public void testFindProductByAccountId() { - Product p = repository.findByAccountId("123"); + Product p = repository.findByAccountId(ACCOUNT_ID); + assertNotNull(p); + assertNotNull(p.getId()); + assertEquals(id, p.getId()); + assertEquals(CUSTOMER_ID, p.getCustomerId()); + assertEquals(ProductType.CREDIT, p.getType()); + assertEquals(INITIAL_BALANCE, p.getBalance()); + } + + @Test + @Order(3) + public void testUpdateProductBalance() { + Product product = repository.findById(id).get(); + int newBalance = 15000; + product.setBalance(newBalance); + Product updated = repository.save(product); + assertEquals(newBalance, updated.getBalance()); + assertEquals(id, updated.getId()); + assertEquals(ACCOUNT_ID, updated.getAccountId()); + assertEquals(ProductType.CREDIT, updated.getType()); + } + + @Test + @Order(4) + public void testFindAllProducts() { + List products = repository.findAll(); + assertNotNull(products); + assertFalse(products.isEmpty()); + assertTrue(products.size() >= 1); + } + + @Test + @Order(5) + public void testAddDebitProduct() { + Product p = new Product(); + p.setAccountId("456"); + p.setCustomerId("456"); + p.setType(ProductType.DEBIT); + p.setBalance(5000); + p.setDateOfStart(LocalDate.now()); + p = repository.save(p); assertNotNull(p); assertNotNull(p.getId()); + assertEquals("456", p.getAccountId()); + assertEquals("456", p.getCustomerId()); + assertEquals(ProductType.DEBIT, p.getType()); + assertEquals(5000, p.getBalance()); } + + @Test + @Order(6) + public void testFindNonExistentProduct() { + String randomId = UUID.randomUUID().toString(); + Optional optProduct = repository.findById(randomId); + assertFalse(optProduct.isPresent()); + Product nonExistentProduct = repository.findByAccountId("non-existent-account"); + assertNull(nonExistentProduct); + } + } diff --git a/product-service/src/test/java/pl/piomin/microservices/advanced/product/api/ProductControllerTest.java b/product-service/src/test/java/pl/piomin/microservices/advanced/product/api/ProductControllerTest.java new file mode 100644 index 0000000..8faa66f --- /dev/null +++ b/product-service/src/test/java/pl/piomin/microservices/advanced/product/api/ProductControllerTest.java @@ -0,0 +1,234 @@ + +package pl.piomin.microservices.advanced.product.api; + +import io.specto.hoverfly.junit.core.Hoverfly; +import io.specto.hoverfly.junit.core.config.LogLevel; +import io.specto.hoverfly.junit5.HoverflyExtension; +import io.specto.hoverfly.junit5.api.HoverflyConfig; +import io.specto.hoverfly.junit5.api.HoverflyCore; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; +import org.testcontainers.containers.MongoDBContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; +import pl.piomin.microservices.advanced.product.model.Product; +import pl.piomin.microservices.advanced.product.model.ProductType; + +import java.time.LocalDate; +import java.util.List; + +import static io.specto.hoverfly.junit.core.SimulationSource.dsl; +import static io.specto.hoverfly.junit.dsl.HoverflyDsl.service; +import static io.specto.hoverfly.junit.dsl.ResponseCreators.success; +import static io.specto.hoverfly.junit.dsl.matchers.HoverflyMatchers.startsWith; +import static org.junit.jupiter.api.Assertions.*; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, + properties = {"spring.cloud.discovery.enabled=false"}) +@Testcontainers +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +@HoverflyCore(config = @HoverflyConfig(logLevel = LogLevel.DEBUG)) +@ExtendWith(HoverflyExtension.class) +public class ProductControllerTest { + + @Container + static MongoDBContainer mongoDBContainer = new MongoDBContainer("mongo:8.0"); + + @DynamicPropertySource + static void registerMongoProperties(DynamicPropertyRegistry registry) { + registry.add("spring.data.mongodb.uri", () -> mongoDBContainer.getConnectionString() + "/test"); + } + + @Autowired + TestRestTemplate template; + + private static String productId; + private static final String ACCOUNT_ID = "ACC987654"; + private static final String CUSTOMER_ID = "CUST987654"; + private static final int INITIAL_BALANCE = 10000; + + @Test + @Order(1) + public void testAddProduct() { + Product product = new Product(); + product.setAccountId(ACCOUNT_ID); + product.setCustomerId(CUSTOMER_ID); + product.setType(ProductType.CREDIT); + product.setBalance(INITIAL_BALANCE); + product.setDateOfStart(LocalDate.now()); + + ResponseEntity response = template.postForEntity("/products", product, Product.class); + assertEquals(HttpStatus.OK, response.getStatusCode()); + Product created = response.getBody(); + assertNotNull(created); + assertNotNull(created.getId()); + assertEquals(ACCOUNT_ID, created.getAccountId()); + assertEquals(CUSTOMER_ID, created.getCustomerId()); + assertEquals(ProductType.CREDIT, created.getType()); + assertEquals(INITIAL_BALANCE, created.getBalance()); + assertNotNull(created.getDateOfStart()); + productId = created.getId(); + } + + @Test + @Order(2) + public void testFindByAccountId() { + ResponseEntity response = template.getForEntity("/products/account/{accountId}", Product.class, ACCOUNT_ID); + assertEquals(HttpStatus.OK, response.getStatusCode()); + Product found = response.getBody(); + assertNotNull(found); + assertEquals(productId, found.getId()); + assertEquals(ACCOUNT_ID, found.getAccountId()); + assertEquals(CUSTOMER_ID, found.getCustomerId()); + assertEquals(ProductType.CREDIT, found.getType()); + } + + @Test + @Order(3) + public void testFindById(Hoverfly hoverfly) { + hoverfly.simulate( + dsl(service("http://account-service") + .get(startsWith("/accounts/" + productId)) + .willReturn(success("{\"id\":\"" + productId + "\",\"customerId\":\"" + CUSTOMER_ID + "\"}", "application/json")))); + ResponseEntity response = template.getForEntity("/products/{id}", Product.class, productId); + assertEquals(HttpStatus.OK, response.getStatusCode()); + Product found = response.getBody(); + assertNotNull(found); + assertEquals(productId, found.getId()); + assertEquals(ACCOUNT_ID, found.getAccountId()); + assertEquals(CUSTOMER_ID, found.getCustomerId()); + } + + @Test + @Order(4) + public void testFindAll() { + ResponseEntity> response = template.exchange( + "/products", HttpMethod.GET, null, new ParameterizedTypeReference>() {}); + assertEquals(HttpStatus.OK, response.getStatusCode()); + assertNotNull(response.getBody()); + assertFalse(response.getBody().isEmpty()); + } + + @Test + @Order(5) + public void testFindByNonExistentAccountId() { + ResponseEntity response = template.getForEntity( + "/products/account/{accountId}", Product.class, "non-existent-account"); + assertEquals(HttpStatus.OK, response.getStatusCode()); + assertNull(response.getBody()); + } +} + +package pl.piomin.microservices.advanced.product.api; + +import io.specto.hoverfly.junit.core.SimulationSource; +import io.specto.hoverfly.junit.dsl.HoverflyDsl; +import io.specto.hoverfly.junit.dsl.ResponseCreators; +import io.specto.hoverfly.junit.dsl.matchers.HoverflyMatchers; +import io.specto.hoverfly.junit5.HoverflyExtension; +import io.specto.hoverfly.junit5.api.HoverflyConfig; +import io.specto.hoverfly.junit5.api.HoverflyCore; +import io.specto.hoverfly.junit.core.config.LogLevel; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestMethodOrder; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.containers.MongoDBContainer; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; +import pl.piomin.microservices.advanced.product.model.Product; +import pl.piomin.microservices.advanced.product.model.ProductType; + +import java.time.LocalDate; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, + properties = {"spring.cloud.discovery.enabled=false"}) +@Testcontainers +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +@HoverflyCore(config = @HoverflyConfig(logLevel = LogLevel.DEBUG)) +@ExtendWith(HoverflyExtension.class) +public class ProductControllerTest { + + @Container + static MongoDBContainer mongoDB = new MongoDBContainer("mongo:8.0"); + + @DynamicPropertySource + static void setProps(DynamicPropertyRegistry registry) { + registry.add("spring.data.mongodb.uri", () -> mongoDB.getConnectionString() + "/test"); + } + + @Autowired + TestRestTemplate restTemplate; + + private static String id; + private static final String ACCOUNT = "ACC987654"; + private static final String CUSTOMER = "CUST987654"; + + @Test @Order(1) + public void testAddProduct() { + Product p = new Product(); + p.setAccountId(ACCOUNT); + p.setCustomerId(CUSTOMER); + p.setType(ProductType.CREDIT); + p.setBalance(10000); + p.setDateOfStart(LocalDate.now()); + ResponseEntity r = restTemplate.postForEntity("/products", p, Product.class); + assertEquals(HttpStatus.OK, r.getStatusCode()); + id = r.getBody().getId(); + } + + @Test @Order(2) + public void testFindByAccountId() { + ResponseEntity r = restTemplate.getForEntity("/products/account/{acct}", Product.class, ACCOUNT); + assertEquals(id, r.getBody().getId()); + } + + @Test @Order(3) + public void testFindById() { + // mock account-service response + HoverflyDsl.service("http://account-service") + .get(HoverflyMatchers.startsWith("/accounts/" + id)) + .willReturn(ResponseCreators.success("{\"id\":\""+id+"\",\"customerId\":\""+CUSTOMER+"\"}", "application/json")); + ResponseEntity r = restTemplate.getForEntity("/products/{id}", Product.class, id); + assertEquals(CUSTOMER, r.getBody().getCustomerId()); + } + + @Test @Order(4) + public void testFindAll() { + ResponseEntity> r = restTemplate.exchange( + "/products", HttpMethod.GET, null, + new ParameterizedTypeReference>(){}); + assertFalse(r.getBody().isEmpty()); + } + + @Test @Order(5) + public void testNonExistentAccount() { + ResponseEntity r = restTemplate.getForEntity("/products/account/{acct}", Product.class, "no-such"); + assertEquals(null, r.getBody()); + } +} diff --git a/product-service/src/test/java/pl/piomin/microservices/advanced/product/config/ProductContainersConfiguration.java b/product-service/src/test/java/pl/piomin/microservices/advanced/product/config/ProductContainersConfiguration.java new file mode 100644 index 0000000..bdcbe35 --- /dev/null +++ b/product-service/src/test/java/pl/piomin/microservices/advanced/product/config/ProductContainersConfiguration.java @@ -0,0 +1,60 @@ +package pl.piomin.microservices.advanced.product.config; + +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; +import org.testcontainers.containers.MongoDBContainer; +import org.testcontainers.junit.jupiter.Container; + +@TestConfiguration +public class ProductContainersConfiguration { + + @Container + private static final MongoDBContainer mongoDBContainer = new MongoDBContainer("mongo:8.0"); + + static { + mongoDBContainer.start(); + } + + @DynamicPropertySource + static void setProperties(DynamicPropertyRegistry registry) { + String uri = mongoDBContainer.getConnectionString() + "/test"; + registry.add("spring.data.mongodb.uri", () -> uri); + } + + @Bean + public MongoDBContainer mongoDbContainer() { + return mongoDBContainer; + } +} + +package pl.piomin.microservices.advanced.product.config; + +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; +import org.testcontainers.containers.MongoDBContainer; +import org.testcontainers.junit.jupiter.Container; + +@TestConfiguration +public class ProductContainersConfiguration { + + @Container + private static final MongoDBContainer mongoDBContainer = new MongoDBContainer("mongo:8.0"); + + static { + mongoDBContainer.start(); + } + + @DynamicPropertySource + static void setProperties(DynamicPropertyRegistry registry) { + registry.add("spring.data.mongodb.uri", () -> mongoDBContainer.getConnectionString() + "/test"); + } + + @Bean + public MongoDBContainer mongoDbContainer() { + return mongoDBContainer; + } +}