Test Get method using MockMvc and Mockito - java

I'm working on writing test case using MockMvc and Mokito.
Assume I have a list of order:
{
{
"order_id": 1,
"user_id": 1,
"price": 11.0,
"order_status": "Pending",
},
{
"order_id": 2,
"user_id": 2,
"price": 12.0,
"order_status": "Cancelled",
},
{
"order_id": 3,
"user_id": 1,
"price": 13.0,
"order_status": "Delivered",
},
}
The column order_id is unique since I set it as primary key. But one user can have multiple orders so the column user_id can appear multiple times.
When I tried the endpoint /api/order/getOrders/user/{user_id} in Postman (For example, I set user_id = 1). The response is exactly same what I expected:
{
{
"order_id": 1,
"user_id": 1,
"price": 11.0,
"order_status": "Pending",
},
{
"order_id": 3,
"user_id": 1,
"price": 13.0,
"order_status": "Delivered",
},
}
However, when I tried to write the unit test case using MockMvc and Mockito. It always return all the orders. Here is my code:
List<Order> orderList = new ArrayList<>();
Order order1 = new Order(1, 1, 11.0, "Pending");
Order order2 = new Order(2, 2, 12.0, "Cancelled");
Order order3 = new Order(3, 1, 13.0, "Shipped");
orderList.add(order1);
orderList.add(order2);
orderList.add(order3);
Mockito.when(orderService.getOrdersUserId(1)).thenReturn(orderList);
mockMvc.perform(MockMvcRequestBuilders.get("/api/order/getOrders/user/{user_id}", 1).contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andDo(print())
.andExpect(jsonPath("$", hasSize(2)));
The test is failed because the response include all 3 items. I believe that I was wrong by using thenReturn(orderList) but I have no idea to fix it.
Can someone let me know how can I fix it, please?

The order list that you return has all three orders in it so it's always going to return all of them. If you are mocking the behaviour then just add orders 1 and 3
List<Order> orderList = new ArrayList<>();
Order order1 = new Order(1, 1, 11.0, "Pending");
Order order2 = new Order(2, 2, 12.0, "Cancelled");
Order order3 = new Order(3, 1, 13.0, "Shipped");
orderList.add(order1);
orderList.add(order3);

Related

My List instances show result in a part, and blank in another part

I have a Product Entity with the name of a Product, price, brand etc.
I have a Store Entity with a Promotion Entity instance based on season -> if is Easter, Promotion for whole Store Products is somehow 10% reduced and so on.
I have a Promotion Entity, with a PromotionSeason(easter, christmas etc) and a List to see what products get that reduced price.
I have an Category Entity which have an instance of Promotion Entity, which, have a List products instance too, to see what Promotion this category have
I have a Set of categories in our store.
Problem is, if i save a Promotion to Store, that promotion works, i mean in the List instance of a Store Promotion, it shows what products at are promotion.
But if i set Promotion for a Category, it sets List correctly, but now that List products from Store Promotions show a blank array '[]' and viceversa, i don't know why it happening like this.
In the DB, i get associations between primary and foreig keys correctly, just in the Postman Response is this thing
Store Service class addPromotion method:
public Store addPromotion(String storeName, String promotionType) {
Optional<Store> storeOptional = Optional.ofNullable(getStoreByStoreName(storeName));
if(storeOptional.isPresent()) {
Promotion promotion = callingOthers.getPromotionBasedOnSeason(promotionType.toLowerCase());
Session session = entityManager.unwrap(Session.class);
session.update(promotion);
storeOptional.get().setPromotion(promotion);
Set<Category> categorySet = storeOptional.get().getCategorySet();
List<Product> productCollection = new ArrayList<>();
categorySet.forEach(category -> productCollection.addAll(category.getProductCollection()));
promotion.setNumberOfProductsAtPromotion(numberOfProductsAtPromotion(productCollection));
promotion.setProductList(productCollection);
promotion.getProductList().forEach(
product -> product.setProductPrice(discountedPrice(product.getProductPrice(), promotion.getPromotionSeason().applySeasonPromotionDiscount(product.getProductPrice()))));
// promotion.setPromotionStore(storeOptional.get());
storeRepository.save(storeOptional.get());
return storeOptional.get();
}
return storeOptional.get();
}
Category Service addPromotion method:
public Category addPromotionToCategory(String categoryName, String promotionType) {
Category category = discountPromotionForCategory(categoryName, promotionType);
categoryRepository.save(category);
return category;
}
private Category discountPromotionForCategory(String categoryName, String promotionType)
{
Category category = categoryRepository.getCategoryByCategoryDescription_DescriptionName(categoryName);
Promotion promotion = callPromotion(promotionType);
// List<Product> productCollection = new ArrayList<>(category.getProductCollection());
// promotion.setProductList(productCollection);
// promotion.setNumberOfProductsAtPromotion(numberOfProductsAtPromotion(category.getProductCollection()));
category.getProductCollection().forEach(promotion::addProduct);
promotion.setNumberOfProductsAtPromotion(numberOfProductsAtPromotion(category.getProductCollection()));
category.getProductCollection()
.forEach(product -> product.setProductPrice(
discountedPrice(product.getProductPrice(), promotion.getPromotionSeason().applySeasonPromotionDiscount(product.getProductPrice()))));
Session session = entityManager.unwrap(Session.class);
session.update(promotion);
promotion.getProductList().forEach(session::update);
category.setPromotion(promotion);
categoryRepository.save(category);
return category;
}
Again, problem is, my list got changed between methods, if i set a promotion to Store, List from Category Promotion show blank, same is for the other way around
What to do?
Edited:
So when i do a POST Request to set a Promotion for a Store, output is like this:
"storeId": 1,
"storeLocation": {
"locationCity": "Suceava",
"locationCountry": "Romania",
"locationZipCode": {
"zipCode": "123456"
}
},
"storeName": "Catena",
"storeType": "MEDICAL_STORE",
"categorySet": [
{
"categoryId": 1,
"categoryDescription": {
"descriptionName": "Biotics",
"descriptionAbout": "Etyc"
},
"productCollection": [
{
"productId": 1,
"productPrice": 10.09,
"productQuantity": 19,
"productDescription": {
"descriptionName": "Colebil",
"descriptionAbout": "Etc"
},
"productStatus": "PRODUCT_AVAILABLE",
"productExpDate": "2023-02-28",
"productProducedAtDate": "2022-08-29T17:53:38.799+00:00"
}
],
"promotion": {
"promotionId": 1,
"numberOfProductsAtPromotion": 19,
"promotionSeason": {
"promotion": "easterPromotion"
},
"productList": []
}
}
],
"promotion": {
"promotionId": 2,
"numberOfProductsAtPromotion": 19,
"promotionSeason": {
"promotion": "christmasPromotion",
"promotionDiscountForChristmasIs": 2.99
},
"productList": [
{
"productId": 1,
"productPrice": 10.09,
"productQuantity": 19,
"productDescription": {
"descriptionName": "Colebil",
"descriptionAbout": "Etc"
},
"productStatus": "PRODUCT_AVAILABLE",
"productExpDate": "2023-02-28",
"productProducedAtDate": "2022-08-29T17:53:38.799+00:00"
}
]
}
}
But when i do a POST Request to set a Promotion just for a specific Category, even i have setted previously a Promotion for the whole Store, output is like this:
"storeId": 1,
"storeLocation": {
"locationCity": "Suceava",
"locationCountry": "Romania",
"locationZipCode": {
"zipCode": "123456"
}
},
"storeName": "Catena",
"storeType": "MEDICAL_STORE",
"categorySet": [
{
"categoryId": 1,
"categoryDescription": {
"descriptionName": "Biotics",
"descriptionAbout": "Etyc"
},
"productCollection": [
{
"productId": 1,
"productPrice": 10.09,
"productQuantity": 19,
"productDescription": {
"descriptionName": "Colebil",
"descriptionAbout": "Etc"
},
"productStatus": "PRODUCT_AVAILABLE",
"productExpDate": "2023-02-28",
"productProducedAtDate": "2022-08-29T17:53:38.799+00:00"
}
],
"promotion": {
"promotionId": 1,
"numberOfProductsAtPromotion": 19,
"promotionSeason": {
"promotion": "easterPromotion"
},
"productList": [
{
"productId": 1,
"productPrice": 10.09,
"productQuantity": 19,
"productDescription": {
"descriptionName": "Colebil",
"descriptionAbout": "Etc"
},
"productStatus": "PRODUCT_AVAILABLE",
"productExpDate": "2023-02-28",
"productProducedAtDate": "2022-08-29T17:53:38.799+00:00"
}
]
}
}
],
"promotion": {
"promotionId": 2,
"numberOfProductsAtPromotion": 19,
"promotionSeason": {
"promotion": "christmasPromotion",
"promotionDiscountForChristmasIs": 2.99
},
"productList": []
}
}
So the problem is i should see both of ProductList instances populated in Response, but the bug is i just see one, why is happening this?

How to get value from json using restassured

I have json and there is array of 'products'.
{
"data": [
{
"contact_id": "...",
"email": "...",
"first_name": "...",
"hash_campaign": "",
"hash_campaign_valid_to_date": null,
"hash_password": "",
"last_name": "...",
"loans": [
],
"max_available_loan_amount": 2000.00,
"middle_name": "P",
"mobile": "...",
"personal_id": "...",
"product_code": 2,
"products": [
{
"available_loan_terms": [
15,
21,
30,
7,
45
],
"default_amount": 0,
"default_term": 15,
"document_required": 0,
"max_available_loan_amount": 2000.00,
"max_loan_amount": 0,
"max_monthly_payment": 0.00,
"product_code": 2
},
{
"available_loan_terms": [
3,
6,
4,
5
],
"default_amount": 0,
"default_term": 0,
"document_required": 0,
"max_available_loan_amount": 4000.00,
"max_loan_amount": 0,
"max_monthly_payment": 1300.00,
"product_code": 101
},
{
"available_loan_terms": [
3,
6,
4,
5
],
"default_amount": 0,
"default_term": 0,
"document_required": 0,
"max_available_loan_amount": 3000.00,
"max_loan_amount": 0,
"max_monthly_payment": 1510.00,
"product_code": 100
}
],
"scoring_through_zoral": "0"
}
],
"description": "...",
"requestId": "...",
"status": 8888
}
I would like to get values of fields 'default_term' and 'max_available_loan_amount' only for product with code 2.
I use restassured
I've tried
List<List> lists = response.body().jsonPath().getList("data.products");
but this code returns list with only one item, I mean all products in one item...
how can I get information for first item in products array from this json ???
Step 1: Create POJO to mapping
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
#Data
#JsonIgnoreProperties(ignoreUnknown = true)
public static class Product {
#JsonProperty("default_term")
private int default_term;
#JsonProperty("max_available_loan_amount")
private double max_available_loan_amount;
}
Step 2: Extract response and deserialize to object.
Product product = ...jsonPath().getObject("data[0].products.find {it.product_code == 2}", Product.class);
System.out.println(product);
//Product(default_term=15, max_available_loan_amount=2000.0)
This could work
List<Integer> li_defaultTerm = response.getBody().jsonPath().get("$..products[?(#.product_code=='2')].default_term");
System.out.println(li_defaultTerm.get(0));
//15
List<Double> li_MaxAvailLoanAmount = response.getBody().jsonPath().get("$..products[?(#.product_code=='2')].max_available_loan_amount");
System.out.println(li_MaxAvailLoanAmount.get(0));
//2000.0

kotlin list group by with sort

solution for solving list
group by price with sort by rank
my list is bellow
and I want a output like bellow response like -
Rank 1 , price -5000
Rank 2-4 , price - 1000
Rank 5-8,price 500
please provide solution for that
"rank": [
{
"id": 627,
"group_id": 1,
"rank": 1,
"price": 5000,
"status": true,
"created_at": "2021-08-06T12:57:24.000000Z",
"updated_at": "2021-08-06T12:57:24.000000Z"
},
{
"id": 628,
"group_id": 1,
"rank": 2,
"price": 1000,
"status": true,
"created_at": "2021-08-06T12:57:24.000000Z",
"updated_at": "2021-08-06T12:57:24.000000Z"
}
]
}```
Assuming you are able to deserialize your Json to Kotlin Data Class, you can adapt following code...
data class InitialItem(val rank: Int, val price: Int)
data class FinalItem(val rankStart: Int?, val rankEnd: Int?, val price: Int)
val initialList = listOf(
InitialItem(1, 5000),
InitialItem(2, 1000),
InitialItem(3, 1000),
InitialItem(4, 1000),
InitialItem(5, 500),
InitialItem(6, 500),
InitialItem(7, 500),
InitialItem(8, 500)
)
val finalList = initialList
.groupBy { it.price }
.map { FinalItem(it.value.minOfOrNull { it.rank }, it.value.maxOfOrNull { it.rank }, it.key) }
.sortedBy { it.rankStart }

How to use MongoDB Java driver to group by dayOfYear on ISODate attributes?

How to use mongodb java driver to compare dayOfYear of two ISODate objects?
Here are my docs
{"name": "hello", "count": 4, "TIMESTAMP": ISODate("2017-10-02T02:00:35.098Z")}
{"name": "hello", "count": 5, "TIMESTAMP": ISODate("2017-10-02T02:00:35.098Z")}
{"name": "goodbye", "count": 6, "TIMESTAMP": ISODate("2017-10-01T02:00:35.098Z")}
{"name": "foo", "count": 6, "TIMESTAMP": ISODate("2017-10-02T02:00:35.098Z")}
I want to compare the day in "TIMESTAMP" to perform some aggregation
Bson match = Aggregates.match(eq("name": "hello"));
Bson group = Aggregates.group(new Document("name", "$name"), Accumulators.sum("total", 1));
collection.aggregate(Arrays.asList(match, group))
Now I am not sure how to do this aggregation for all the records that belongs to particular day?
so my expected result for "2017-10-02" is
[{"_id": {"name":"hello"}, "total": 9}, {"_id": {"name":"foo"}, "total": 6}]
Given the following documents:
{"name": "hello", "count": 4, "TIMESTAMP": ISODate("2017-10-02T02:00:35.098Z")}
{"name": "hello", "count": 5, "TIMESTAMP": ISODate("2017-10-02T02:00:35.098Z")}
{"name": "goodbye", "count": 6, "TIMESTAMP": ISODate("2017-10-01T02:00:35.098Z")}
{"name": "foo", "count": 6, "TIMESTAMP": ISODate("2017-10-02T02:00:35.098Z")}
The following command ...
db.getCollection('dayOfYear').aggregate([
// project dayOfYear as an attribute
{ $project: { name: 1, count: 1, dayOfYear: { $dayOfYear: "$TIMESTAMP" } } },
// match documents with dayOfYear=275
{ $match: { dayOfYear: 275 } },
// sum the count attribute for the selected day and name
{ $group : { _id : { name: "$name" }, total: { $sum: "$count" } } }
])
... will return:
{
"_id" : {
"name" : "foo"
},
"total" : 6
}
{
"_id" : {
"name" : "hello"
},
"total" : 9
}
I think this meets the requirement expressed in your OP.
Here's the same command expressed using the MongoDB Java driver:
MongoCollection<Document> collection = mongoClient.getDatabase("stackoverflow").getCollection("dayOfYear");
Document project = new Document("name", 1)
.append("count", 1)
.append("dayOfYear", new Document("$dayOfYear", "$TIMESTAMP"));
Document dayOfYearMatch = new Document("dayOfYear", 275);
Document grouping = new Document("_id", "$name").append("total", new Document("$sum", "$count"));
AggregateIterable<Document> documents = collection.aggregate(Arrays.asList(
new Document("$project", project),
new Document("$match", dayOfYearMatch),
new Document("$group", grouping)
));
for (Document document : documents) {
logger.info("{}", document.toJson());
}
Update based on this comment:
One of the problems with project is that it only include fields you specify . The above input is just an example. I have 100 fields in my doc I can't sepecify every single one so if I use project I have to specify all 100 fields in addition to "dayOfYear" field. – user1870400 11 mins ago
You can use the following command to return the same output but without a $project stage:
db.getCollection('dayOfYear').aggregate([
// ignore any documents which do not match dayOfYear=275
{ "$redact": {
"$cond": {
if: { $eq: [ { $dayOfYear: "$TIMESTAMP" }, 275 ] },
"then": "$$KEEP",
"else": "$$PRUNE"
}
}},
// sum the count attribute for the selected day
{ $group : { _id : { name: "$name" }, total: { $sum: "$count" } } }
])
Here's that command in its 'Java form':
MongoCollection<Document> collection = mongoClient.getDatabase("stackoverflow").getCollection("dayOfYear");
Document redact = new Document("$cond", new Document("if", new Document("$eq", Arrays.asList(new Document("$dayOfYear", "$TIMESTAMP"), 275)))
.append("then", "$$KEEP")
.append("else", "$$PRUNE"));
Document grouping = new Document("_id", "$name").append("total", new Document("$sum", "$count"));
AggregateIterable<Document> documents = collection.aggregate(Arrays.asList(
new Document("$redact", redact),
new Document("$group", grouping)
));
for (Document document : documents) {
logger.info("{}", document.toJson());
}
Note: Depending on the size of your collection/your non functional requirements/etc you may want to consider the performance of these solutions and either (a) add a match stage before you start projecting/redacting or (b) extract dayOfYear into its own attribute so that you can avoid this complexity entirely.

filter a json array (which has million items) based on search criteria

I am at loss of finding the best way to filter a json array (which has million items) based on some search criteria which keeps on changning.
eg: find all items based on region_id and pool_id
The json array format as below
[
{
"url": "webservices/rest/resources/1/",
"id": 1,
"name": "con A",
"is_parent": 1,
"account_id": 1,
"pool_id": 4,
"region_id": 5,
"market_id": 1,
"baseline_type": "Type 1",
"is_producer": 0,
"utilisation_type": 0,
"forecasting_algorithm": "Clipped nominal capacity",
"availability_protocol": null,
"communication_protocol": "OPC",
"activation_protocol": [
" Demo"
],
"installed_capacity": 2000.0,
"nominal_capacity": 1000.0,
"positive_tolerance": 300.0,
"negative_tolerance": 300.0,
"capacity_fee": 20.0,
"energy_fee": 20.0,
"activation_fee": 10.0,
"parent_resource": null
},
{
"url": "webservices/rest/resources/2/",
"id": 2,
"name": "con B",
"is_parent": 1,
"account_id": 2,
"pool_id": 1,
"region_id": 4,
"market_id": 1,
"baseline_type": "Type 1 DW",
"is_producer": 1,
"utilisation_type": 0,
"forecasting_algorithm": "Clipped nominal capacity",
"availability_protocol": null,
"communication_protocol": " Demo",
"activation_protocol": [
" Demo"
],
"installed_capacity": 3000.0,
"nominal_capacity": 1000.0,
"positive_tolerance": 300.0,
"negative_tolerance": 300.0,
"capacity_fee": 20.0,
"energy_fee": 20.0,
"activation_fee": 10.0,
"parent_resource": null
},
.
.
. // million items
]
I tried using the following api's in java
Jackson api for converting the json to java objects.
Google Guava api for filtering java objects.
Is it the best procedure to filter the json data? If not, please advice.

Categories

Resources