From a0ca06fe4597fe640ba505e7c4a8890353cf78f2 Mon Sep 17 00:00:00 2001 From: indu sankar Date: Fri, 13 Dec 2019 14:09:48 +0530 Subject: [PATCH] Testcases for products-service,bookstore in java (#11) * Testcases for products-service,bookstore * Put back 'sap.capire.bookstore-Books_texts.csv' file, ignored it in DataLoader. --- bookstore/srv/pom.xml | 5 + .../bookstore/handlers/orderServiceTest.java | 165 ++++++++++++++++++ .../cap/bookstore/testUtil/CsvUploader.java | 82 +++++++++ .../cap/bookstore/testUtil/DataLoader.java | 45 +++++ .../srv/src/test/resources/application.yaml | 7 + products-service/srv/pom.xml | 5 + .../productsservice/productServiceTest.java | 124 +++++++++++++ .../srv/src/test/resources/application.yaml | 7 + 8 files changed, 440 insertions(+) create mode 100644 bookstore/srv/src/test/java/com/sap/teched/cap/bookstore/handlers/orderServiceTest.java create mode 100644 bookstore/srv/src/test/java/com/sap/teched/cap/bookstore/testUtil/CsvUploader.java create mode 100644 bookstore/srv/src/test/java/com/sap/teched/cap/bookstore/testUtil/DataLoader.java create mode 100644 bookstore/srv/src/test/resources/application.yaml create mode 100644 products-service/srv/src/test/java/com/sap/teched/cap/productsservice/productServiceTest.java create mode 100644 products-service/srv/src/test/resources/application.yaml diff --git a/bookstore/srv/pom.xml b/bookstore/srv/pom.xml index b63ccc78..afee7e4f 100644 --- a/bookstore/srv/pom.xml +++ b/bookstore/srv/pom.xml @@ -35,6 +35,11 @@ org.xerial sqlite-jdbc + + + org.springframework.boot + spring-boot-starter-test + diff --git a/bookstore/srv/src/test/java/com/sap/teched/cap/bookstore/handlers/orderServiceTest.java b/bookstore/srv/src/test/java/com/sap/teched/cap/bookstore/handlers/orderServiceTest.java new file mode 100644 index 00000000..bebbc797 --- /dev/null +++ b/bookstore/srv/src/test/java/com/sap/teched/cap/bookstore/handlers/orderServiceTest.java @@ -0,0 +1,165 @@ +package com.sap.teched.cap.bookstore.handlers; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.not; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.springframework.http.MediaType.APPLICATION_JSON_UTF8; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.util.ArrayList; +import java.util.List; + +import org.json.JSONArray; +import org.json.JSONObject; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; + +import sap.capire.bookstore.OrderItems; + +@RunWith(SpringRunner.class) +@SpringBootTest +@AutoConfigureMockMvc +public class orderServiceTest { + + private static final String ODATA_V4 = "/odata/v4"; + private static final String BOOKS_URI = ODATA_V4 + "/BooksService/Books"; + private static final String ORDERS_URI = ODATA_V4 + "/OrdersService/Orders"; + private static final String ORDER_ITEMS_URI = ODATA_V4 + "/OrdersService/OrderItems"; + + @Autowired + private MockMvc mockMvc; + + @Test + public void testGetBooks() throws Exception { + + mockMvc.perform(get(BOOKS_URI).content("")).andExpect(status().isOk()) + .andExpect(jsonPath("$.value[0].title", is("Wuthering Heights"))); + } + + @Test + public void testCreateOrderItem() throws Exception { + + final String data = "{\"parent_ID\": \"12345678-aaaa-bbbb-dddd-ddddeeeeffef\",\"book_ID\": \"abed2f7a-c50e-4bc5-89fd-9a00a54b4b16\", \"amount\": 1 }"; + + mockMvc.perform(post(ORDER_ITEMS_URI).contentType(APPLICATION_JSON_UTF8).content(data)) + .andExpect(status().isCreated()); + + mockMvc.perform(get(ORDER_ITEMS_URI).content("")).andExpect(status().isOk()) + .andExpect(jsonPath("$.value[0].parent_ID", is("12345678-aaaa-bbbb-dddd-ddddeeeeffef"))); + } + + @Test + public void tesValidateBookAndDecreaseStock() throws Exception { + + final String data = "{\"parent_ID\": \"12345678-aaaa-bbbb-dddd-ddddeeeeffee\",\"book_ID\": \"5e69a718-d86b-4461-8953-0edadcd87960\", \"amount\": 20 }"; + + mockMvc.perform(post(ORDER_ITEMS_URI).contentType(APPLICATION_JSON_UTF8).content(data)) + .andExpect(status().isCreated()); + + mockMvc.perform(post(ORDER_ITEMS_URI).contentType(APPLICATION_JSON_UTF8).content(data)) + .andExpect(status().isBadRequest()); + + } + + @Test + public void tesCalculateNetAmount() throws Exception { + + final String data = "{\"parent_ID\": \"12345678-aaaa-bbbb-dddd-ddddeeeeffbb\",\"book_ID\": \"b7bca6dd-0497-465e-9a5a-56f244174c8c\", \"amount\": 10 }"; + + MvcResult result = mockMvc.perform(post(ORDER_ITEMS_URI).contentType(APPLICATION_JSON_UTF8).content(data)) + .andReturn(); + + JSONObject jsonObj = new JSONObject(result.getResponse().getContentAsString()); + + String id = jsonObj.get("ID").toString(); + + mockMvc.perform(get(ORDER_ITEMS_URI+ "(" + id + ")").content("")).andExpect(status().isOk()) + .andExpect(jsonPath("$.netAmount", is(141.4))); + + } + + + @Test + public void testCreateOrder() throws Exception { + + final String orderData = "{\r\n" + + " \"items\": [{\r\n" + + " \"parent_ID\": \"12345678-aaaa-bbbb-dddd-ddddeeeeffef\",\r\n" + + " \"book_ID\": \"abed2f7a-c50e-4bc5-89fd-9a00a54b4b16\",\r\n" + + " \"amount\": 1\r\n" + + " }, {\r\n" + + " \"parent_ID\": \"12345678-aaaa-bbbb-dddd-ddddeeeeffef\",\r\n" + + " \"book_ID\": \"b7bca6dd-0497-465e-9a5a-56f244174c8c\",\r\n" + + " \"amount\": 1\r\n" + + " }]\r\n" + + "}"; + + + mockMvc.perform(post(ORDERS_URI).contentType(APPLICATION_JSON_UTF8).content( + orderData)) .andExpect(status().isCreated()); + + } + + @Test + public void testCalculateTotal() throws Exception { + + final String orderData = "{\r\n" + + " \"items\": [{\r\n" + + " \"parent_ID\": \"12345678-aaaa-bbbb-dddd-ddddeeeeffef\",\r\n" + + " \"book_ID\": \"abed2f7a-c50e-4bc5-89fd-9a00a54b4b16\",\r\n" + + " \"amount\": 1\r\n" + + " }, {\r\n" + + " \"parent_ID\": \"12345678-aaaa-bbbb-dddd-ddddeeeeffef\",\r\n" + + " \"book_ID\": \"b7bca6dd-0497-465e-9a5a-56f244174c8c\",\r\n" + + " \"amount\": 2\r\n" + + " }]\r\n" + + "}"; + + MvcResult result = mockMvc.perform(post(ORDERS_URI).contentType(APPLICATION_JSON_UTF8).content(orderData)) + .andReturn(); + + JSONObject jsonObj = new JSONObject(result.getResponse().getContentAsString()); + + String id = jsonObj.get("ID").toString(); + + mockMvc.perform(get(ORDERS_URI+ "(" + id + ")").content("")).andExpect(status().isOk()) + .andExpect(jsonPath("$.total", is(39.39))); + + } + + @Test + public void testValidateBookAndDecreaseStockViaOrders() throws Exception { + + final String orderData = "{\r\n" + + " \"items\": [{\r\n" + + " \"parent_ID\": \"12345678-aaaa-bbbb-dddd-ddddeeeeffef\",\r\n" + + " \"book_ID\": \"fd0c5fda-8811-4e20-bcff-3a776abc290a\",\r\n" + + " \"amount\": 300\r\n" + + " }, {\r\n" + + " \"parent_ID\": \"12345678-aaaa-bbbb-dddd-ddddeeeeffef\",\r\n" + + " \"book_ID\": \"b7bca6dd-0497-465e-9a5a-56f244174c8c\",\r\n" + + " \"amount\": 1\r\n" + + " }]\r\n" + + "}"; + mockMvc.perform(post(ORDERS_URI).contentType(APPLICATION_JSON_UTF8).content(orderData)) + .andExpect(status().isCreated()); + + mockMvc.perform(post(ORDERS_URI).contentType(APPLICATION_JSON_UTF8).content(orderData)) + .andExpect(status().isBadRequest()); + + } + + +} \ No newline at end of file diff --git a/bookstore/srv/src/test/java/com/sap/teched/cap/bookstore/testUtil/CsvUploader.java b/bookstore/srv/src/test/java/com/sap/teched/cap/bookstore/testUtil/CsvUploader.java new file mode 100644 index 00000000..a45310e0 --- /dev/null +++ b/bookstore/srv/src/test/java/com/sap/teched/cap/bookstore/testUtil/CsvUploader.java @@ -0,0 +1,82 @@ +package com.sap.teched.cap.bookstore.testUtil; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.sap.cds.ql.Insert; +import com.sap.cds.reflect.CdsElement; +import com.sap.cds.reflect.CdsEntity; +import com.sap.cds.reflect.CdsModel; +import com.sap.cds.reflect.CdsSimpleType; +import com.sap.cds.services.persistence.PersistenceService; + +public class CsvUploader { + + private final CdsModel model; + private final PersistenceService ds; + + public CsvUploader(CdsModel model, PersistenceService ds) { + this.model = model; + this.ds = ds; + } + + void insertContent(File file) throws FileNotFoundException, IOException { + String fileName = file.getName(); + String entityName = fileName.replace("-", ".").substring(0, fileName.length() - 4); + CdsEntity entity = model.getEntity(entityName); + List> data = new ArrayList<>(); + + try (BufferedReader br = new BufferedReader(new FileReader(file))) { + String line = br.readLine(); + CdsElement[] headers = getHeaders(entity, line); + while ((line = br.readLine()) != null) { + Map row = new HashMap<>(); + String[] values = line.split(";"); + for (int i = 0; i < headers.length; i++) { + CdsElement element = headers[i]; + String typeName = element.getType().as(CdsSimpleType.class).getQualifiedName(); + final Object value; + String txt = values[i]; + if ("".equals(txt)) { + continue; + } + switch (typeName) { + case "cds.Integer": + value = Integer.valueOf(txt); + break; + case "cds.Date": + value = LocalDate.parse(txt); + break; + default: + value = txt; + } + row.put(element.getName(), value); + } + + data.add(row); + } + } + + Insert insert = Insert.into(entity).entries(data); + ds.run(insert); + } + + private CdsElement[] getHeaders(CdsEntity entity, String line) { + String[] elementNames = line.split(";"); + CdsElement[] result = new CdsElement[elementNames.length]; + for (int i = 0; i < elementNames.length; i++) { + result[i] = entity.getElement(elementNames[i]); + } + + return result; + } + +} diff --git a/bookstore/srv/src/test/java/com/sap/teched/cap/bookstore/testUtil/DataLoader.java b/bookstore/srv/src/test/java/com/sap/teched/cap/bookstore/testUtil/DataLoader.java new file mode 100644 index 00000000..55385c9e --- /dev/null +++ b/bookstore/srv/src/test/java/com/sap/teched/cap/bookstore/testUtil/DataLoader.java @@ -0,0 +1,45 @@ +package com.sap.teched.cap.bookstore.testUtil; + +import java.io.File; +import java.io.IOException; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.ApplicationArguments; +import org.springframework.boot.ApplicationRunner; +import org.springframework.stereotype.Component; + +import com.sap.cds.services.persistence.PersistenceService; +import com.sap.cds.services.runtime.CdsRuntime; + +@Component +public class DataLoader implements ApplicationRunner { + + @Autowired + private CdsRuntime runtime; + + public void run(ApplicationArguments args) { + + PersistenceService ds = (PersistenceService) runtime.getServiceCatalog() + .getService(PersistenceService.DEFAULT_NAME); + + runtime.runInRequestContext(null, r -> { + runtime.runInChangeSetContext(c -> { + File folder = new File("../db/data"); + CsvUploader uploader = new CsvUploader(runtime.getCdsModel(), ds); + for (File file : folder.listFiles()) { + try { + if(file.getName().equals("sap.capire.bookstore-Books_texts.csv")) + continue; + uploader.insertContent(file); + } catch (RuntimeException | IOException e) { + throw new RuntimeException("exception reading file " + file.getName(), e); + } + } + + return null; + }); + + return null; + }); + } +} \ No newline at end of file diff --git a/bookstore/srv/src/test/resources/application.yaml b/bookstore/srv/src/test/resources/application.yaml new file mode 100644 index 00000000..c81ea4f5 --- /dev/null +++ b/bookstore/srv/src/test/resources/application.yaml @@ -0,0 +1,7 @@ +--- +spring: + profiles: default + datasource: + url: "jdbc:sqlite::memory:" + driver-class-name: org.sqlite.JDBC + initialization-mode: always diff --git a/products-service/srv/pom.xml b/products-service/srv/pom.xml index b04b95dd..5b89c08f 100644 --- a/products-service/srv/pom.xml +++ b/products-service/srv/pom.xml @@ -25,6 +25,11 @@ org.xerial sqlite-jdbc + + + org.springframework.boot + spring-boot-starter-test + diff --git a/products-service/srv/src/test/java/com/sap/teched/cap/productsservice/productServiceTest.java b/products-service/srv/src/test/java/com/sap/teched/cap/productsservice/productServiceTest.java new file mode 100644 index 00000000..63356549 --- /dev/null +++ b/products-service/srv/src/test/java/com/sap/teched/cap/productsservice/productServiceTest.java @@ -0,0 +1,124 @@ +package com.sap.teched.cap.productsservice; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.not; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.springframework.http.MediaType.APPLICATION_JSON_UTF8; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.web.servlet.MockMvc; + +@RunWith(SpringRunner.class) +@SpringBootTest +@AutoConfigureMockMvc +public class productServiceTest { + + private static final String ODATA_V4 = "/odata/v4"; + private static final String PRODUCTS_URI = ODATA_V4 + "/AdminService/Products"; + private static final String CATEGORIES_URI = ODATA_V4 + "/AdminService/Categories"; + private static final String CURRENCIES_URI = ODATA_V4 + "/AdminService/Currencies"; + + @Autowired + private MockMvc mockMvc; + + @Test + public void testProducts() throws Exception { + mockMvc.perform(get(PRODUCTS_URI).content("")).andExpect(status().isOk()); + } + + @Test + public void testPostProducts() throws Exception { + final String data = "{\"ID\": \"12345678-aaaa-bbbb-cccc-ddddeeeeffff\", \"title\": \"Awesome product\", \"descr\": \"It is really really awesome!\"}"; + + mockMvc.perform(post(PRODUCTS_URI).contentType(APPLICATION_JSON_UTF8).content(data)) + .andExpect(status().isCreated()); + } + + @Test + public void testGetProduct() throws Exception { + final String id = "12345611-aaaa-bbbb-cccc-ddddeeeeffef"; + final String data = "{\"ID\": \"12345611-aaaa-bbbb-cccc-ddddeeeeffef\", \"title\": \"Awesome book\", \"descr\": \"It is an awesome book!\"}"; + + mockMvc.perform(post(PRODUCTS_URI).contentType(APPLICATION_JSON_UTF8).content(data)) + .andExpect(status().isCreated()); + + mockMvc.perform(get(PRODUCTS_URI + "(" + id + ")").content("")).andExpect(status().isOk()) + .andExpect(jsonPath("$.title", is("Awesome book"))); + } + + @Test + public void testEditProduct() throws Exception { + final String id = "12345678-aaaa-bbbb-dddd-ddddeeeeffef"; + final String data = "{\"ID\": \"12345678-aaaa-bbbb-dddd-ddddeeeeffef\", \"title\": \"Awesome book\", \"descr\": \"It is an awesome book!\"}"; + final String changedData = "{\"ID\": \"12345678-aaaa-bbbb-dddd-ddddeeeeffef\", \"title\": \"Awesome book\", \"descr\": \"It is a good book! I love it\"}"; + + mockMvc.perform(post(PRODUCTS_URI).contentType(APPLICATION_JSON_UTF8).content(data)) + .andExpect(status().isCreated()); + + mockMvc.perform(put(PRODUCTS_URI + "(" + id + ")").contentType(APPLICATION_JSON_UTF8).content(changedData)) + .andExpect(status().isOk()).andExpect(jsonPath("$.modifiedAt", is(not(nullValue())))); + } + + @Test + public void testDeleteProduct() throws Exception { + final String id = "12345678-aaaa-bbbb-cccc-ddddeeeeffdd"; + final String data = "{\"ID\": \"12345678-aaaa-bbbb-cccc-ddddeeeeffdd\", \"title\": \"Bad book\", \"descr\": \"It is a very bad book!\"}"; + + mockMvc.perform(post(PRODUCTS_URI).contentType(APPLICATION_JSON_UTF8).content(data)) + .andExpect(status().isCreated()); + + mockMvc.perform(delete(PRODUCTS_URI + "(" + id + ")").content("")).andExpect(status().isNoContent()); + + mockMvc.perform(get(PRODUCTS_URI + "(" + id + ")").content("")).andExpect(status().isNotFound()); + } + + @Test + public void testGetProductWhenProductIDNotPresent() throws Exception { + final String data = "{\"ID\": \"12345678-aaaa-bbbb-cccc-ddddeeeeffaa\", \"title\": \"Another book\", \"descr\": \"It is bad book!\"}"; + + mockMvc.perform(post(PRODUCTS_URI).contentType(APPLICATION_JSON_UTF8).content(data)) + .andExpect(status().isCreated()); + + mockMvc.perform(get(PRODUCTS_URI + "(123)").content("")).andExpect(status().isBadRequest()); + } + + @Test + public void testPostCategories() throws Exception { + final String data = "{\"ID\": 2, \"parent_ID\": 1, \"name\": \"Fiction\"}"; + + mockMvc.perform(post(CATEGORIES_URI).contentType(APPLICATION_JSON_UTF8).content(data)) + .andExpect(status().isCreated()); + } + + @Test + public void testEditCategories() throws Exception { + final String data = "{\"ID\": 3, \"parent_ID\": 1, \"name\": \"Fiction\"}"; + final String changedData = "{\"ID\": 3, \"name\": \"Science Fiction\"}"; + + mockMvc.perform(post(CATEGORIES_URI).contentType(APPLICATION_JSON_UTF8).content(data)) + .andExpect(status().isCreated()); + + mockMvc.perform(put(CATEGORIES_URI + "(3)").contentType(APPLICATION_JSON_UTF8).content(changedData)) + .andExpect(status().isOk()); + } + + @Test + public void testPostCurrencies() throws Exception { + final String data = "{\"code\": \"USD\", \"symbol\": \"$\", \"name\": \"US Dollar\", \"descr\": \"United States Dollar\"}"; + + mockMvc.perform(post(CURRENCIES_URI).contentType(APPLICATION_JSON_UTF8).content(data)) + .andExpect(status().isCreated()); + } + +} \ No newline at end of file diff --git a/products-service/srv/src/test/resources/application.yaml b/products-service/srv/src/test/resources/application.yaml new file mode 100644 index 00000000..c81ea4f5 --- /dev/null +++ b/products-service/srv/src/test/resources/application.yaml @@ -0,0 +1,7 @@ +--- +spring: + profiles: default + datasource: + url: "jdbc:sqlite::memory:" + driver-class-name: org.sqlite.JDBC + initialization-mode: always