Commit 6fe8956f authored by vikram singh's avatar vikram singh

initial commit

parents
HELP.md
.gradle
build/
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**
!**/src/test/**
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
out/
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
### VS Code ###
.vscode/
***ECOM-STORE***
**Description**
`This Project is consisting of ecom-like application where different users can order thier items and if item is not not available he gets out of stock messages (based on the conditions applied)`
`Here I had tried to make the things very simple and focused on the logic implementation`
**Technologies used**
*Java 1.8, Mysql,SpringBoot,Juint5, JPA,Hibernate Mapping,RestFul Webservices, Gradle,Postman,*
**How to Run the Appliation**
clone the project using https://github.com/vikram026/ecom-store.git
build the project and make sure all the component test cases are passed
Once the build is success run the springboot application;
**Prerequisites**
1.Mysql should be installed in local with user name root and no password;
create database "ecomdb" tables will be created by hibernate
**Actual Process**
**ItemPreparation**
2.prepare the data by hitting the API using Postman
a.Create 10 items in item table using postman using below url and body in json;
POST: http://localhost:8991/item (for save/update)
with body like below:
{
"id":1,
"name":"pencil",
"qty":100,
"price":20
}
like that prepare more or less 10 items so that one can order more than one item;
3.once the data is prepared
test these data using GET:- http://localhost:8991/item
it will list all the item with its id;
using these itemId we are going to order items;
4. one can delete the item using DELETE:-http://localhost:8991/item?id=2 here id is itemid
Placing the Order
single/bulk order by customer
5. POST:-localhost:8991/order
A customer can order single or multiple item or more then one quantity of single item changing the payload
payload for single item be like :-
{
"orderId":1,
"orderedItems":[
{
"id":5,
"itemId":1,
"qty":1
}
],
"emailId":"vikram19977@gmail.com"
}
payload for more than one quantity of single item
{
"orderId":1,
"orderedItems":[
{
"id":5,
"itemId":1,
"qty":4
}
],
"emailId":"vikram19977@gmail.com"
}
payload for more then one item
{
"orderId":1,
"orderedItems":[
{
"id":5,
"itemId":1,
"qty":1
},
{
"id":5,
"itemId":1,
"qty":1
}
],
"emailId":"testuser@gmail.com"
}
i. If we have happy path means order is placed then we will get the message like ::
'sample output'- "Order Placed...! you have spent :"+xxxx +" Rupees"; xxxx=calculated total spent amount;
ii. for any of the exception like out of stock item we have various messages coming to the customer accordinglg
It is already tested by various component test cases written in test folder
for both ItemController and OrderController;
6.GET:localhost:8991/order -> for listing all orders placed by all the customers
sample output:
[
{
"orderId": 66,
"orderedItems": [
{
"id": 67,
"itemId": 1,
"qty": 30
},
{
"id": 68,
"itemId": 3,
"qty": 2
}
],
"emailId": "vikram@234.com",
"amount": 2150
},
{
"orderId": 69,
"orderedItems": [
{
"id": 70,
"itemId": 1,
"qty": 5
},
{
"id": 71,
"itemId": 2,
"qty": 5
}
],
"emailId": "vikram@234.com",
"amount": 250025
},
{
"orderId": 72,
"orderedItems": [
{
"id": 73,
"itemId": 1,
"qty": 5
},
{
"id": 74,
"itemId": 2,
"qty": 5
}
],
"emailId": "vik123@gmail.com",
"amount": 250025
}
]
7.GET:localhost:8991/order/vik123@gmail.com -> for listing the orders per customer separately;
here email id is customer email id;
sample output:
[
{
"orderId": 72,
"orderedItems": [
{
"id": 73,
"itemId": 1,
"qty": 5
},
{
"id": 74,
"itemId": 2,
"qty": 5
}
],
"emailId": "vik123@gmail.com",
"amount": 250025
}
]
8.In TestCases I have used Junit5 conects as well with the 87% of testcase coverage;
\ No newline at end of file
plugins {
id 'org.springframework.boot' version '2.2.6.RELEASE'
id 'io.spring.dependency-management' version '1.0.9.RELEASE'
id 'java'
}
group = 'com.ecom'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
configurations {
developmentOnly
runtimeClasspath {
extendsFrom developmentOnly
}
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-actuator'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'mysql:mysql-connector-java'
annotationProcessor 'org.projectlombok:lombok'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
}
test {
useJUnitPlatform()
}
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
exec "$JAVACMD" "$@"
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
rootProject.name = 'ecom-store'
package com.ecom;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class EcomStoreApplication {
public static void main(String[] args) {
SpringApplication.run(EcomStoreApplication.class, args);
}
}
package com.ecom.common;
public interface EcomUtils {
String ERROR_IN_DB="Some error in DB could not process your order";
String SUCCESS_MESSAGE = "Order Placed...! you have spent :";
String RUPEES = " Rupees";
String GET_ORDER_URL ="http://localhost:8991/order/";
String ITEMS_QUANTITY_SHOULD_NOT_BE_ZERO ="Item's quantity should not be 0 please add item" ;
}
package com.ecom.controller;
import com.ecom.model.Item;
import com.ecom.service.ItemService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Optional;
@RestController
@RequestMapping("item")
@Slf4j
public class ItemController {
@Autowired
private ItemService itemService;
@PostMapping
public ResponseEntity<Item> save(@RequestBody Item item){
log.info("into controller save method");
Item savedItem= itemService.save(item);
if(savedItem!=null)
return new ResponseEntity<>(savedItem,HttpStatus.CREATED);
else
return new ResponseEntity<>(savedItem,HttpStatus.INTERNAL_SERVER_ERROR);
}
@GetMapping("/{id}")
public ResponseEntity<Optional<Item>> getById(@PathVariable int id){
log.info("into controller getById method");
Optional<Item> items= itemService.findById(id);
if(items.isPresent())
return new ResponseEntity<>(items, HttpStatus.OK);
else
return new ResponseEntity<>(items, HttpStatus.NOT_FOUND);
}
@GetMapping
public ResponseEntity<List<Item>> getAll(){
log.info("into getAll method " );
List<Item> items= itemService.findAll();
if(items!=null && !items.isEmpty())
return new ResponseEntity<>(items, HttpStatus.OK);
else
return new ResponseEntity<>(items, HttpStatus.NOT_FOUND);
}
@DeleteMapping
public ResponseEntity<String> deleteById(@RequestParam int id){
log.info("into controllers Delete method for item");
String response= itemService.deleteById(id);
return new ResponseEntity<>(response, HttpStatus.OK);
}
}
package com.ecom.controller;
import com.ecom.model.Orders;
import com.ecom.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("order")
@Slf4j
public class OrderController {
@Autowired
private OrderService orderService;
@PostMapping
public ResponseEntity<String> orderItems(@RequestBody Orders orders){
log.info("Into save method of Order");
String response= orderService.processOrder(orders);
log.info("response after process {} "+response);
return !orderService.isOutOfStock() ?
new ResponseEntity<>(response, HttpStatus.OK)
: new ResponseEntity<>(response, HttpStatus.NOT_ACCEPTABLE);
}
@GetMapping
public ResponseEntity<List<Orders>> getAllOrders(){
log.info("into Order getAllItem method");
List<Orders> orders= orderService.getAll();
return orders!=null && !orders.isEmpty() ? new ResponseEntity<>(orders, HttpStatus.OK)
:new ResponseEntity<>(orders, HttpStatus.INTERNAL_SERVER_ERROR);
}
@GetMapping("/{emailId}")
public ResponseEntity<List<Orders>> getOrderDetailsByCustomerEmailId(@PathVariable String emailId ){
log.info("into find all order by emailid mehtod ");
List<Orders> orders= orderService.findOrderDetailsByEmailId(emailId);
log.info("orders details after the call"+orders);
return orders!=null && !orders.isEmpty() ? new ResponseEntity<>(orders, HttpStatus.OK)
:new ResponseEntity<>(orders, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
package com.ecom.model;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
@Entity
@Data
@NoArgsConstructor
public class Item {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Column(name="name")
private String name;
@Column(name="qty")
private int qty;
@Column(name="price")
private int price;
}
package com.ecom.model;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Data
@NoArgsConstructor
@Entity
public class OrderedItems {
@Id @GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private int itemId;
private int qty;
}
package com.ecom.model;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.util.List;
@Data
@Entity
@NoArgsConstructor
public class Orders {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int orderId;
@OneToMany(targetEntity = OrderedItems.class,cascade = CascadeType.ALL)
@JoinColumn(name = "orderId",referencedColumnName = "orderId")
private List<OrderedItems> orderedItems;
private String emailId;
private int amount;
}
package com.ecom.repository;
import com.ecom.model.Item;
import org.springframework.data.jpa.repository.JpaRepository;
public interface ItemRepository extends JpaRepository<Item,Integer> {
}
package com.ecom.repository;
import com.ecom.model.Orders;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
public interface OrderRepository extends JpaRepository<Orders, Integer> {
List<Orders> findByEmailId(String emailId);
}
package com.ecom.repository;
import com.ecom.model.OrderedItems;
import org.springframework.data.jpa.repository.JpaRepository;
public interface OrderedItemsRepository extends JpaRepository<OrderedItems,Integer> {
}
package com.ecom.service;
import com.ecom.model.Item;
import java.util.List;
import java.util.Optional;
public interface ItemService {
Item save(Item item);
Optional<Item> findById(int id);
String deleteById(int id);
List<Item> findAll();
}
package com.ecom.service;
import com.ecom.model.Orders;
import java.util.List;
public interface OrderService {
String processOrder(Orders orders);
boolean isOutOfStock();
List<Orders> getAll();
List<Orders> findOrderDetailsByEmailId(String emailId);
}
package com.ecom.service.impl;
import com.ecom.model.Item;
import com.ecom.repository.ItemRepository;
import com.ecom.service.ItemService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
@Service
@Slf4j
public class ItemServiceImpl implements ItemService {
@Autowired
private ItemRepository itemRepository;
@Override
public Item save(Item item) {
return itemRepository.save(item);
}
@Override
public Optional<Item> findById(int id) {
return itemRepository.findById(id);
}
@Override
public String deleteById(int id) {
try{
itemRepository.deleteById(id);
return "Item with id "+id+" is deleted";
}catch (Exception e){
log.error("Item with id is not available");
e.getMessage();
return "Item with id is not available or db is down ";
}
}
@Override
public List<Item> findAll() {
log.info("into findAll service ");
return itemRepository.findAll();
}
}
package com.ecom.service.impl;
import com.ecom.common.EcomUtils;
import com.ecom.model.Item;
import com.ecom.model.OrderedItems;
import com.ecom.model.Orders;
import com.ecom.repository.OrderRepository;
import com.ecom.repository.OrderedItemsRepository;
import com.ecom.service.ItemService;
import com.ecom.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
@Service
@Slf4j
public class OrderServiceImpl implements OrderService {
@Autowired
private OrderRepository orderRepository;
@Autowired
private OrderedItemsRepository orderedItemsRepository;
@Autowired
private ItemService itemService;
private String response;
private boolean outOfStock;
int totalAmount;
@Override
public boolean isOutOfStock(){
return outOfStock;
}
@Override
public String processOrder(Orders orders) {
response="";
outOfStock=false;
totalAmount=0;
try {
log.info("Into Process Order method");
process(orders.getOrderedItems());
if(!outOfStock) {
log.info("Total purchase amount : " + totalAmount);
orders.setAmount(totalAmount);
Orders ordersSaved = orderRepository.save(orders);
log.info("order after saved into database is " + ordersSaved);
response=EcomUtils.SUCCESS_MESSAGE+totalAmount+EcomUtils.RUPEES
+" Please visite the "+EcomUtils.GET_ORDER_URL+orders.getEmailId();
return response;
}
}catch (Exception e){
log.error("could not saved into db");
e.printStackTrace();
response= EcomUtils.ERROR_IN_DB;
}
return response;
}
@Override
public List<Orders> getAll() {
log.info("Before calling getAll method to Db");
return orderRepository.findAll();
}
@Override
public List<Orders> findOrderDetailsByEmailId(String emailId) {
log.info("before Db call ");
return orderRepository.findByEmailId(emailId);
}
private void process(List<OrderedItems> orderedItemsList) {
log.info("started processing/calculating the order ");
for(OrderedItems e:orderedItemsList){
Optional<Item> itemOptional=itemService.findById(e.getItemId());
if(itemOptional.isPresent()){
Item item=itemOptional.get();
log.info("item available in the cart is "+item);
if( e.getQty()!=0 && e.getQty()<=item.getQty()){
totalAmount+=e.getQty()*item.getPrice();
item.setQty(item.getQty()-e.getQty());
itemService.save(item);
}
else if(e.getQty()==0){
response=EcomUtils.ITEMS_QUANTITY_SHOULD_NOT_BE_ZERO;
}
else{
response=item.getQty()>0?"item "+item.getName()+" with id="+e.getItemId()+" is the first item we found out of stock for your purchase You can purchase only "+item.getQty()+" "+item.getName()
:"Item " +item.getName()+"with id="+e.getItemId()+" is out of Stock please visit after some time.";
outOfStock=true;
break;
}
}else {
response="Item with id "+e.getItemId()+" not available please visit after some time.";
outOfStock=true;
break;
}
}
}
}
server.port=8991
spring.datasource.url = jdbc:mysql://localhost:3306/ecomdb?useSSL=false
spring.datasource.username = root
spring.datasource.password =
spring.jpa.show-sql = true
spring.jpa.hibernate.ddl-auto = update
spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
package com.ecom;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class EcomStoreApplicationTests {
@Test
void contextLoads() {
}
}
package com.ecom.config;
import com.ecom.repository.ItemRepository;
import com.ecom.repository.OrderRepository;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.test.mock.mockito.MockBean;
@TestConfiguration
public class TestConfig {
@MockBean
private ItemRepository itemRepository;
@MockBean
private OrderRepository orderRepository;
}
\ No newline at end of file
package com.ecom.controller;
import com.ecom.config.TestConfig;
import com.ecom.model.Item;
import com.ecom.repository.ItemRepository;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.ValueSource;
import org.mockito.ArgumentMatchers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.ContextConfiguration;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.when;
@SpringBootTest
@ContextConfiguration(classes = TestConfig.class)
public class ItemControllerComponentTest {
@Autowired
private ItemController itemController;
@Autowired
private ItemRepository itemRepository;
@DisplayName("This method will test the save method it will mock db ")
@ParameterizedTest
@MethodSource("getItemSource")
public void saveTest(Item item){
when(itemRepository.save(ArgumentMatchers.any(Item.class))).thenReturn(item);
ResponseEntity<Item> responseEntity = itemController.save(item);
assertAll( "savetest",
()-> assertEquals(responseEntity.getStatusCode(), HttpStatus.CREATED,()->"status should be 201")
,()->assertEquals(responseEntity.getBody().getId(),1,()->"id should be mocked id only")
);
}
@DisplayName("This method will test the save method it will mock db ")
@ParameterizedTest
@MethodSource("getItemSource")
public void saveNegativeTest(Item item){
when(itemRepository.save(ArgumentMatchers.any(Item.class))).thenReturn(null);
ResponseEntity<Item> responseEntity = itemController.save(item);
assertAll( "savetestnegative",
()-> assertEquals(responseEntity.getStatusCode(), HttpStatus.INTERNAL_SERVER_ERROR,()->"status should be 500")
,()->assertNull(responseEntity.getBody(),()->"body is null")
);
}
@DisplayName("This method will test the get method it will mock db ")
@ParameterizedTest
@ValueSource(ints={1})
public void getByIdTest(int id){
Item response=mockItem();
when(itemRepository.findById(ArgumentMatchers.anyInt())).thenReturn(Optional.of(response));
ResponseEntity<Optional<Item>> responseEntity = itemController.getById(id);
assertAll( "gettest",
()-> assertEquals(responseEntity.getStatusCode(), HttpStatus.OK,()->"status should be 200")
,()->assertNotNull(responseEntity.getBody(),()->"body is not null")
);
}
@DisplayName("This method will test the get method for negative scenario it will mock db ")
@ParameterizedTest
@ValueSource(ints={1})
public void getByIdTestNegative(int id){
Item response=mockItem();
when(itemRepository.findById(ArgumentMatchers.anyInt())).thenReturn(Optional.ofNullable(null));
ResponseEntity<Optional<Item>> responseEntity = itemController.getById(id);
assertAll( "gettestnegative",
()-> assertEquals(responseEntity.getStatusCode(), HttpStatus.NOT_FOUND,()->"status should be NotFound")
,()->assertEquals(responseEntity.getBody(),Optional.empty(),()->"body is null")
);
}
@DisplayName("This method will test the getAll method it will mock db ")
@Test
public void getAllTest(){
List<Item> response=Arrays.asList(mockItem());
when(itemRepository.findAll()).thenReturn(response);
ResponseEntity<List<Item>> responseEntity = itemController.getAll();
assertAll( "getAllTest",
()-> assertEquals(responseEntity.getStatusCode(), HttpStatus.OK,()->"status should be 200")
,()->assertEquals(responseEntity.getBody(),response,()->"body is List")
);
}
@DisplayName("This method will test the getAll method for Negeate test it will mock db ")
@Test
public void getAllTestNegative(){
List<Item> response=Arrays.asList(mockItem());
when(itemRepository.findAll()).thenReturn(null);
ResponseEntity<List<Item>> responseEntity = itemController.getAll();
assertAll( "getAllTest",
()-> assertEquals(responseEntity.getStatusCode(), HttpStatus.NOT_FOUND,()->"status should be Not found")
,()->assertNull(responseEntity.getBody(),()->"body is null")
);
}
@DisplayName("This method will test the deletebyId method it will mock db ")
@ParameterizedTest
@ValueSource(ints={1})
public void deleteByIdTest(int id){
Item response=mockItem();
doNothing().when(itemRepository).deleteById(ArgumentMatchers.anyInt());
ResponseEntity<String> responseEntity = itemController.deleteById(id);
assertAll( "deleteByIdTest",
()-> assertEquals(responseEntity.getStatusCode(), HttpStatus.OK,()->"status should be OK")
,()->assertEquals(responseEntity.getBody(),"Item with id "+1+" is deleted",()->"body is null")
);
}
private static Stream<Arguments> getItemSource(){
return Stream.of(Arguments.of(mockItem()));
}
public static Item mockItem() {
Item item=new Item();
item.setQty(1);
item.setId(1);
item.setName("test");
item.setPrice(1);
return item;
}
}
package com.ecom.controller;
import com.ecom.config.TestConfig;
import com.ecom.model.Item;
import com.ecom.model.OrderedItems;
import com.ecom.model.Orders;
import com.ecom.repository.ItemRepository;
import com.ecom.repository.OrderRepository;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.ValueSource;
import org.mockito.ArgumentMatchers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.ContextConfiguration;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.when;
@SpringBootTest
@ContextConfiguration(classes = TestConfig.class)
public class OrderControllerComponentTest {
@Autowired
private OrderController orderController;
@Autowired
private OrderRepository orderRepository;
@Autowired
private ItemRepository itemRepository;
@DisplayName("This method will test the orderItems method it will mock db ")
@ParameterizedTest
@MethodSource("getOrdersSource")
public void orderItemsTest(Orders orders){
String actualRespone="Order Placed...! you have spent :"+1+" Rupees"
+" Please visite the http://localhost:8991/order/"+orders.getEmailId();
when(orderRepository.save(ArgumentMatchers.any(Orders.class))).thenReturn(orders);
when(itemRepository.findById(ArgumentMatchers.anyInt())).thenReturn(Optional.of(ItemControllerComponentTest.mockItem()));
when(itemRepository.save(ArgumentMatchers.any(Item.class))).thenReturn(null);
ResponseEntity<String> responseEntity = orderController.orderItems(orders);
assertAll( "orderItemsTest",
()-> assertEquals(responseEntity.getStatusCode(), HttpStatus.OK,()->"status should be 200")
,()->assertEquals(responseEntity.getBody(),actualRespone,()->" messages should match")
);
}
@DisplayName("This method will test the orderItems method for Out of Stock it will mock db ")
@ParameterizedTest
@MethodSource("getOrdersOutOfStockSource")
public void orderItemsOutOfStockTest(Orders orders){
String outOfStockRespone="item "+"test"+" with id="+1+" is the first item we found out of stock for your purchase You can purchase only "+1+" "+"test";
when(orderRepository.save(ArgumentMatchers.any(Orders.class))).thenReturn(orders);
when(itemRepository.findById(ArgumentMatchers.anyInt())).thenReturn(Optional.of(ItemControllerComponentTest.mockItem()));
when(itemRepository.save(ArgumentMatchers.any(Item.class))).thenReturn(null);
ResponseEntity<String> responseEntity = orderController.orderItems(orders);
assertAll( "orderItemsTest",
()-> assertEquals(responseEntity.getStatusCode(), HttpStatus.NOT_ACCEPTABLE,()->"status should be 200")
,()->assertEquals(responseEntity.getBody(),outOfStockRespone,()->" messages should match")
);
}
@DisplayName("This method will test the getOrderDetailsByCustomerEmailId method it will mock db ")
@ParameterizedTest
@ValueSource(strings={"someemail"})
public void getOrderDetailsByCustomerEmailIdTest(String email){
List<Orders> response=Arrays.asList(mockOrders());
when(orderRepository.findByEmailId(ArgumentMatchers.anyString())).thenReturn(response);
ResponseEntity<List<Orders>> responseEntity = orderController.getOrderDetailsByCustomerEmailId(email);
assertAll( "gettest",
()-> assertEquals(responseEntity.getStatusCode(), HttpStatus.OK,()->"status should be 200")
,()->assertNotNull(responseEntity.getBody(),()->"body is not null")
);
}
@DisplayName("This method will test the getOrderDetailsByCustomerEmailId method for negative scenario it will mock db ")
@ParameterizedTest
@ValueSource(strings={"someemail"})
public void getOrderDetailsByCustomerEmailIdTestNegative(String email){
when(orderRepository.findByEmailId(ArgumentMatchers.anyString())).thenReturn(null);
ResponseEntity<List<Orders>> responseEntity = orderController.getOrderDetailsByCustomerEmailId(email);
assertAll( "gettest",
()-> assertEquals(responseEntity.getStatusCode(), HttpStatus.INTERNAL_SERVER_ERROR,()->"status should be 200")
,()->assertNull(responseEntity.getBody(),()->"body is null")
);
}
@DisplayName("This method will test the getAllOrder method it will mock db ")
@Test
public void getAllOrderTest(){
List<Orders> response=Arrays.asList(mockOrders());
when(orderRepository.findAll()).thenReturn(response);
ResponseEntity<List<Orders>> responseEntity = orderController.getAllOrders();
assertAll( "getAllOrdersTest",
()-> assertEquals(responseEntity.getStatusCode(), HttpStatus.OK,()->"status should be 200")
,()->assertEquals(responseEntity.getBody(),response,()->"body is List")
);
}
@DisplayName("This method will test the getAllOrders method for Negeate test it will mock db ")
@Test
public void getAllTestNegative(){
List<Orders> response=Arrays.asList(mockOrders());
when(orderRepository.findAll()).thenReturn(null);
ResponseEntity<List<Orders>> responseEntity = orderController.getAllOrders();
assertAll( "getAllTestNegative",
()-> assertEquals(responseEntity.getStatusCode(), HttpStatus.INTERNAL_SERVER_ERROR,()->"status should be Not found")
,()->assertNull(responseEntity.getBody(),()->"body is null")
);
}
private static Stream<Arguments> getOrdersOutOfStockSource(){
return Stream.of(Arguments.of(mockOutOfStockOrders()));
}
private static Stream<Arguments> getOrdersSource(){
return Stream.of(Arguments.of(mockOrders()));
}
public static Orders mockOrders() {
Orders orders=new Orders();
orders.setOrderId(1);
orders.setEmailId("someemail");
OrderedItems orderedItems=new OrderedItems();
orderedItems.setItemId(1);
orderedItems.setQty(1);
orders.setOrderedItems(Arrays.asList(orderedItems));
return orders;
}
public static Orders mockOutOfStockOrders() {
Orders orders=new Orders();
orders.setOrderId(1);
orders.setEmailId("someemail");
OrderedItems orderedItems=new OrderedItems();
orderedItems.setItemId(1);
orderedItems.setQty(2);
orders.setOrderedItems(Arrays.asList(orderedItems));
return orders;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment