Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
R
reactive-web
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Ashok Kumar K
reactive-web
Commits
1e10cd9f
Commit
1e10cd9f
authored
Sep 24, 2020
by
Ashok Kumar K
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
added unit tests to service layer and few code changes
parent
6cbe12e3
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
186 additions
and
16 deletions
+186
-16
ReactiveWebApplication.java
...in/java/com/nisum/reactiveweb/ReactiveWebApplication.java
+0
-8
ProductHandler.java
...java/com/nisum/reactiveweb/controller/ProductHandler.java
+2
-0
ApiError.java
src/main/java/com/nisum/reactiveweb/exceptions/ApiError.java
+14
-3
GlobalExceptionHandler.java
.../nisum/reactiveweb/exceptions/GlobalExceptionHandler.java
+1
-1
ProductRepositoryImpl.java
...m/nisum/reactiveweb/repository/ProductRepositoryImpl.java
+6
-1
ProductServiceImpl.java
...ava/com/nisum/reactiveweb/service/ProductServiceImpl.java
+3
-3
ProductRepositoryTest.java
...m/nisum/reactiveweb/repository/ProductRepositoryTest.java
+26
-0
ProductServiceTest.java
...ava/com/nisum/reactiveweb/service/ProductServiceTest.java
+134
-0
No files found.
src/main/java/com/nisum/reactiveweb/ReactiveWebApplication.java
View file @
1e10cd9f
package
com
.
nisum
.
reactiveweb
;
package
com
.
nisum
.
reactiveweb
;
import
lombok.extern.slf4j.Slf4j
;
import
reactor.blockhound.BlockHound
;
import
reactor.blockhound.BlockHound
;
import
reactor.core.publisher.Flux
;
import
reactor.core.publisher.Mono
;
import
java.util.concurrent.atomic.AtomicInteger
;
import
org.springframework.boot.SpringApplication
;
import
org.springframework.boot.SpringApplication
;
import
org.springframework.boot.autoconfigure.SpringBootApplication
;
import
org.springframework.boot.autoconfigure.SpringBootApplication
;
import
org.springframework.boot.context.event.ApplicationStartedEvent
;
import
org.springframework.context.event.EventListener
;
import
org.springframework.stereotype.Component
;
@SpringBootApplication
@SpringBootApplication
public
class
ReactiveWebApplication
{
public
class
ReactiveWebApplication
{
...
...
src/main/java/com/nisum/reactiveweb/controller/ProductHandler.java
View file @
1e10cd9f
...
@@ -10,6 +10,7 @@ import org.springframework.beans.factory.annotation.Autowired;
...
@@ -10,6 +10,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.support.DefaultMessageSourceResolvable
;
import
org.springframework.context.support.DefaultMessageSourceResolvable
;
import
org.springframework.stereotype.Component
;
import
org.springframework.stereotype.Component
;
import
org.springframework.util.Assert
;
import
org.springframework.validation.BeanPropertyBindingResult
;
import
org.springframework.validation.BeanPropertyBindingResult
;
import
org.springframework.validation.Errors
;
import
org.springframework.validation.Errors
;
import
org.springframework.validation.Validator
;
import
org.springframework.validation.Validator
;
...
@@ -77,6 +78,7 @@ public class ProductHandler {
...
@@ -77,6 +78,7 @@ public class ProductHandler {
}
}
private
void
validateProduct
(
Product
product
)
{
private
void
validateProduct
(
Product
product
)
{
Assert
.
notNull
(
product
,
"product can't be null"
);
Errors
errors
=
new
BeanPropertyBindingResult
(
product
,
"product"
);
Errors
errors
=
new
BeanPropertyBindingResult
(
product
,
"product"
);
validator
.
validate
(
product
,
errors
);
validator
.
validate
(
product
,
errors
);
String
errorString
=
errors
.
getAllErrors
().
String
errorString
=
errors
.
getAllErrors
().
...
...
src/main/java/com/nisum/reactiveweb/exceptions/ApiError.java
View file @
1e10cd9f
package
com
.
nisum
.
reactiveweb
.
exceptions
;
package
com
.
nisum
.
reactiveweb
.
exceptions
;
import
lombok.extern.slf4j.Slf4j
;
import
java.util.Map
;
import
java.util.Map
;
import
org.springframework.boot.web.error.ErrorAttributeOptions
;
import
org.springframework.boot.web.error.ErrorAttributeOptions
;
...
@@ -8,19 +10,28 @@ import org.springframework.http.HttpStatus;
...
@@ -8,19 +10,28 @@ import org.springframework.http.HttpStatus;
import
org.springframework.stereotype.Component
;
import
org.springframework.stereotype.Component
;
import
org.springframework.web.reactive.function.server.ServerRequest
;
import
org.springframework.web.reactive.function.server.ServerRequest
;
import
static
java
.
util
.
Optional
.
ofNullable
;
import
static
org
.
springframework
.
http
.
HttpStatus
.
BAD_REQUEST
;
import
static
org
.
springframework
.
http
.
HttpStatus
.
INTERNAL_SERVER_ERROR
;
import
static
org
.
springframework
.
http
.
HttpStatus
.
NOT_FOUND
;
@Component
@Component
@Slf4j
public
class
ApiError
extends
DefaultErrorAttributes
{
public
class
ApiError
extends
DefaultErrorAttributes
{
@Override
@Override
public
Map
<
String
,
Object
>
getErrorAttributes
(
ServerRequest
request
,
ErrorAttributeOptions
options
)
{
public
Map
<
String
,
Object
>
getErrorAttributes
(
ServerRequest
request
,
ErrorAttributeOptions
options
)
{
Map
<
String
,
Object
>
errorAttributes
=
super
.
getErrorAttributes
(
request
,
options
);
Map
<
String
,
Object
>
errorAttributes
=
super
.
getErrorAttributes
(
request
,
options
);
Throwable
error
=
getError
(
request
);
Throwable
error
=
getError
(
request
);
log
.
error
(
"{} : {}"
,
error
.
getClass
().
getCanonicalName
(),
error
.
getMessage
());
if
(
error
instanceof
ProductNotFoundException
)
{
if
(
error
instanceof
ProductNotFoundException
)
{
addErrorFields
(
errorAttributes
,
error
,
HttpStatus
.
NOT_FOUND
);
addErrorFields
(
errorAttributes
,
error
,
NOT_FOUND
);
}
else
if
(
error
instanceof
IllegalArgumentException
)
{
}
else
if
(
error
instanceof
IllegalArgumentException
)
{
addErrorFields
(
errorAttributes
,
error
,
HttpStatus
.
BAD_REQUEST
);
addErrorFields
(
errorAttributes
,
error
,
BAD_REQUEST
);
}
else
{
}
else
{
addErrorFields
(
errorAttributes
,
error
,
HttpStatus
.
INTERNAL_SERVER_ERROR
);
int
statusCode
=
(
int
)
ofNullable
(
errorAttributes
.
get
(
"status"
)).
orElse
(
500
);
HttpStatus
status
=
ofNullable
(
HttpStatus
.
resolve
(
statusCode
)).
orElse
(
INTERNAL_SERVER_ERROR
);
addErrorFields
(
errorAttributes
,
error
,
status
);
}
}
return
errorAttributes
;
return
errorAttributes
;
}
}
...
...
src/main/java/com/nisum/reactiveweb/exceptions/GlobalExceptionHandler.java
View file @
1e10cd9f
...
@@ -40,7 +40,7 @@ public class GlobalExceptionHandler extends AbstractErrorWebExceptionHandler {
...
@@ -40,7 +40,7 @@ public class GlobalExceptionHandler extends AbstractErrorWebExceptionHandler {
private
Mono
<
ServerResponse
>
handlerFunction
(
ServerRequest
request
)
{
private
Mono
<
ServerResponse
>
handlerFunction
(
ServerRequest
request
)
{
Map
<
String
,
Object
>
errorAttributes
=
getErrorAttributes
(
request
,
ErrorAttributeOptions
.
defaults
());
Map
<
String
,
Object
>
errorAttributes
=
getErrorAttributes
(
request
,
ErrorAttributeOptions
.
defaults
());
int
status
=
(
int
)
Optional
.
of
(
errorAttributes
.
get
(
"status"
)).
orElse
(
500
);
int
status
=
(
int
)
Optional
.
of
Nullable
(
errorAttributes
.
get
(
"status"
)).
orElse
(
500
);
return
ServerResponse
.
status
(
status
)
return
ServerResponse
.
status
(
status
)
.
contentType
(
MediaType
.
APPLICATION_JSON
)
.
contentType
(
MediaType
.
APPLICATION_JSON
)
...
...
src/main/java/com/nisum/reactiveweb/repository/ProductRepositoryImpl.java
View file @
1e10cd9f
...
@@ -31,7 +31,12 @@ public class ProductRepositoryImpl implements ProductRepository {
...
@@ -31,7 +31,12 @@ public class ProductRepositoryImpl implements ProductRepository {
@Override
@Override
public
Mono
<
Product
>
saveProduct
(
Product
product
)
{
public
Mono
<
Product
>
saveProduct
(
Product
product
)
{
return
template
.
save
(
product
);
return
Mono
.
justOrEmpty
(
product
)
.
map
(
prod
->
{
prod
.
setSku
(
null
);
return
prod
;
})
.
flatMap
(
template:
:
save
);
}
}
@Override
@Override
...
...
src/main/java/com/nisum/reactiveweb/service/ProductServiceImpl.java
View file @
1e10cd9f
...
@@ -29,14 +29,14 @@ public class ProductServiceImpl implements ProductService {
...
@@ -29,14 +29,14 @@ public class ProductServiceImpl implements ProductService {
@Override
@Override
public
Mono
<
Product
>
saveProduct
(
Product
productToSave
)
{
public
Mono
<
Product
>
saveProduct
(
Product
productToSave
)
{
return
Mono
.
just
(
productToSave
)
return
Mono
.
justOrEmpty
(
productToSave
)
.
doOnNext
(
product
->
product
.
setSku
(
null
))
.
flatMap
(
repository:
:
saveProduct
);
.
flatMap
(
repository:
:
saveProduct
);
}
}
@Override
@Override
public
Mono
<
Product
>
updateProduct
(
String
sku
,
Product
product
)
{
public
Mono
<
Product
>
updateProduct
(
String
sku
,
Product
product
)
{
return
getProductBySku
(
sku
)
return
repository
.
getProductBySku
(
sku
)
.
switchIfEmpty
(
Mono
.
error
(
new
ProductNotFoundException
()))
.
then
(
repository
.
updateProduct
(
sku
,
product
));
.
then
(
repository
.
updateProduct
(
sku
,
product
));
}
}
...
...
src/test/java/com/nisum/reactiveweb/repository/ProductRepositoryTest.java
0 → 100644
View file @
1e10cd9f
package
com
.
nisum
.
reactiveweb
.
repository
;
import
org.junit.jupiter.api.Test
;
class
ProductRepositoryTest
{
@Test
void
getProductBySku
()
{
}
@Test
void
getAllProducts
()
{
}
@Test
void
saveProduct
()
{
}
@Test
void
updateProduct
()
{
}
@Test
void
removeProduct
()
{
}
}
\ No newline at end of file
src/test/java/com/nisum/reactiveweb/service/ProductServiceTest.java
0 → 100644
View file @
1e10cd9f
package
com
.
nisum
.
reactiveweb
.
service
;
import
com.nisum.reactiveweb.exceptions.ProductNotFoundException
;
import
com.nisum.reactiveweb.model.Product
;
import
com.nisum.reactiveweb.repository.ProductRepository
;
import
reactor.core.publisher.Flux
;
import
reactor.core.publisher.Mono
;
import
reactor.test.StepVerifier
;
import
java.math.BigDecimal
;
import
java.util.function.Predicate
;
import
org.junit.jupiter.api.Test
;
import
org.mockito.InjectMocks
;
import
org.mockito.Mock
;
import
org.springframework.boot.test.context.SpringBootTest
;
import
static
org
.
mockito
.
ArgumentMatchers
.
any
;
import
static
org
.
mockito
.
ArgumentMatchers
.
anyString
;
import
static
org
.
mockito
.
Mockito
.
when
;
import
static
reactor
.
core
.
publisher
.
Mono
.
just
;
@SpringBootTest
class
ProductServiceTest
{
@InjectMocks
private
ProductServiceImpl
productService
;
@Mock
private
ProductRepository
repository
;
private
final
Product
product1
=
new
Product
(
"1"
,
"toy"
,
new
BigDecimal
(
200
));
private
final
Product
product3
=
new
Product
(
"1"
,
"toy"
,
new
BigDecimal
(
300
));
private
final
Product
product2
=
new
Product
(
"2"
,
"table"
,
new
BigDecimal
(
400
));
private
final
Predicate
<
Product
>
productPredicate1
=
productPredicate
(
"1"
,
"toy"
,
200
);
private
final
Predicate
<
Product
>
productPredicate3
=
productPredicate
(
"1"
,
"toy"
,
300
);
private
final
Predicate
<
Product
>
productPredicate2
=
productPredicate
(
"2"
,
"table"
,
400
);
@Test
void
getProductBySkuWhenProductExists
()
{
when
(
repository
.
getProductBySku
(
"1"
)).
thenReturn
(
productMono
());
StepVerifier
.
create
(
productService
.
getProductBySku
(
"1"
))
.
expectNextMatches
(
productPredicate1
)
.
verifyComplete
();
}
@Test
void
getProductBySkuWhenProductDoesNotExist
()
{
when
(
repository
.
getProductBySku
(
"1"
)).
thenReturn
(
Mono
.
empty
());
StepVerifier
.
create
(
productService
.
getProductBySku
(
"1"
))
.
expectError
(
ProductNotFoundException
.
class
)
.
verify
();
}
@Test
void
getAllProducts
()
{
when
(
repository
.
getAllProducts
()).
thenReturn
(
productsFlux
());
StepVerifier
.
create
(
productService
.
getAllProducts
())
.
expectNextMatches
(
productPredicate1
)
.
as
(
"predicate1"
)
.
expectNextMatches
(
productPredicate2
)
.
as
(
"predicate2"
)
.
verifyComplete
();
}
@Test
void
saveProduct
()
{
when
(
repository
.
saveProduct
(
any
(
Product
.
class
))).
thenReturn
(
productMono
());
StepVerifier
.
create
(
productService
.
saveProduct
(
product1
))
.
expectNextMatches
(
productPredicate1
)
.
verifyComplete
();
}
@Test
void
updateProductWhenProductExists
()
{
when
(
repository
.
getProductBySku
(
anyString
())).
thenReturn
(
productMono
());
when
(
repository
.
updateProduct
(
anyString
(),
any
(
Product
.
class
))).
thenReturn
(
just
(
product3
));
StepVerifier
.
create
(
productService
.
updateProduct
(
"1"
,
product3
))
.
expectNextMatches
(
productPredicate3
)
.
verifyComplete
();
}
@Test
void
updateProductWhenProductDoesNotExist
()
{
when
(
repository
.
getProductBySku
(
"1"
)).
thenReturn
(
Mono
.
empty
());
when
(
repository
.
updateProduct
(
anyString
(),
any
(
Product
.
class
))).
thenReturn
(
just
(
product3
));
StepVerifier
.
create
(
productService
.
updateProduct
(
"1"
,
product3
))
.
expectError
(
ProductNotFoundException
.
class
)
.
verify
();
}
@Test
void
removeProductWhenProductExists
()
{
when
(
repository
.
removeProduct
(
anyString
())).
thenReturn
(
just
(
1L
));
StepVerifier
.
create
(
productService
.
removeProduct
(
"1"
))
.
expectNext
(
"deleted"
)
.
verifyComplete
();
}
@Test
void
removeProductWhenProductDoesNotExist
()
{
when
(
repository
.
removeProduct
(
anyString
())).
thenReturn
(
just
(
0L
));
StepVerifier
.
create
(
productService
.
removeProduct
(
"1"
))
.
expectError
(
ProductNotFoundException
.
class
)
.
verify
();
}
private
Mono
<
Product
>
productMono
()
{
return
just
(
product1
);
}
private
Flux
<
Product
>
productsFlux
()
{
return
Flux
.
just
(
product1
,
product2
);
}
private
Predicate
<
Product
>
productPredicate
(
String
sku
,
String
name
,
int
price
)
{
return
product
->
product
.
getSku
().
equals
(
sku
)
&&
product
.
getName
().
equals
(
name
)
&&
product
.
getPrice
().
intValue
()
==
price
;
}
}
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment