i want to match output of get-request, and match with manual provided json string, basically copy one json string coming out of whole output and test. Tried lot of ways but its not happening, i can't delete all rows from database to match one string to one, so, i want to match only one json string -- Like this below
{
"instanceName": "",
"read": 1,
"swProduct": "Area 1",
"swProductModule": "Regular 1"
},
Here's, my test code ---
#SpringBootTest(classes = TestApplication.class)
#ActiveProfiles("dev")
#AutoConfigureMockMvc
public class SwStatusCheckTest {
#Autowired
private MockMvc mvc;
#IfProfileValue(name = "spring.profiles.active", values = { "dev" })
#Test
#DisplayName("GET Method /SwCheckStatus check success")
public void testStatusSuccess() throws Exception {
MvcResult result = mvc.perform(get("/status/SwCheckStatus"))
.andDo(print())
.andExpect(status().isOk())
.andReturn();
//.andExpect(content().json("{\"services\":[\"OutboundMessageService\"]}", true));
String actualJson = result.getResponse().getContentAsString();
String expectedJson = "[{\"instanceName\":\"Instance C\", \"read\" : 1, \"swProduct\" : \"Area 3\", \"swProductModule\" : \"Spring Boot 3\"}]";
assertThat(expectedJson).isIn(actualJson);
}
}
Output of whole Postman json result looks like this ---
[
{
"instanceName": "",
"read": 1,
"swProduct": "Area 1",
"swProductModule": "Regular 1"
},
{
"instanceName": "",
"read": 1,
"swProduct": "Area 1",
"swProductModule": "Regular 2"
},
{
"instanceName": "",
"read": 1,
"swProduct": "Area 1",
"swProductModule": "Spring Boot 1"
},
{
"instanceName": "",
"read": 1,
"swProduct": "Area 1",
"swProductModule": "Spring Boot 2"
},
Intellij says -- its expecting and String matches... but test failed -- check attachment ---
[enter image description here][1]
Any help of insights to perform the test is greatly appreciated.
[1]: https://i.stack.imgur.com/FE2dT.jpg
isIn is not for comparing strings, but arrays.
You can compare JSON as Map, with jackson-databind and Google Guava:
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Maps;
import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
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.annotation.IfProfileValue;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
#SpringBootTest(classes = TestApplication.class)
#ActiveProfiles("dev")
#AutoConfigureMockMvc
public class SwStatusCheckTest {
#Autowired
private MockMvc mvc;
#IfProfileValue(name = "spring.profiles.active", values = { "dev" })
#Test
#DisplayName("GET Method /SwCheckStatus check success")
public void testStatusSuccess() throws Exception {
MvcResult result = mvc.perform(get("/status/SwCheckStatus"))
.andDo(print())
.andExpect(status().isOk())
.andReturn();
//.andExpect(content().json("{\"services\":[\"OutboundMessageService\"]}", true));
ObjectMapper mapper = new ObjectMapper();
List<? extends Map<String, Object>> actualJson = mapper.readValue(result.getResponse().getContentAsString(),
List.class);
Map<String, Object> expected = Map.of("instanceName", "", "read", 1, "swProduct", "Area 1", "swProductModule",
"Regular 1");
boolean contains = false;
for (Map<String, Object> a : actualJson) {
boolean res = Maps.difference(a, expected).areEqual();
if (res) {
contains = true;
break;
}
}
assertThat(contains).isTrue();
}
}
If I'm reading your question right as well as the image you posted, the problem is either the expected/actual Strings or the condition (assertion) defined in the test. The "actual" String value is an array of several elements, the "expected" is an array of only one element. Since the array of just one element is NOT contained in the array of several elements, it won't work.
If the code is changed such that the "expected" value you're looking for is written as JUST the object (without its enclosing array)
{ ... your object here ... }
Then the expected "isIn" actual assertion should work.
Related
I was using JPA AttributeConverter with Spring Boot 1.2.1 RELEASE and it worked fine. But I get the following error after upgrading to Spring Boot 1.3.0.RELEASE
attributeLabelMap.java:
I want to add this as the json format
metadata: {
masked: true,
maxLength: 200,
formula: "a + b",
parentCode: "strAttr_1",
currency: "$",
},
I added this column in entity class
#Column(name = "metadata_json",columnDefinition = "json")
#Convert(converter = HashMapConverter.class)
private Map<String,Object> metaDataAttribute
HashMapConverter class:
package in.nobroker.hood.crm.entity;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import javax.persistence.AttributeConverter;
import java.io.IOException;
import java.util.Map;
#Slf4j
public class HashMapConverter implements AttributeConverter<Map<String, Object>, String> {
private final ObjectMapper objectMapper = new ObjectMapper();
#Override
public String convertToDatabaseColumn(Map<String, Object> stringObjectMap) {
String attributeInfoJson = null;
try {
attributeInfoJson = objectMapper.writeValueAsString(stringObjectMap);
} catch (final JsonProcessingException e) {
log.error("JSON writing error", e);
}
return attributeInfoJson;
}
#Override
public Map<String, Object> convertToEntityAttribute(String s) {
Map<String, Object> attributeInfo = null;
try {
attributeInfo = objectMapper.readValue(s, Map.class);
} catch (final IOException e) {
log.error("JSON reading error", e);
}
return attributeInfo;
}
}
In Postman:
{
"label": "dateAttr_5",
"id": "f73434ba-bfaa-49f5-9a41-b86715a985f2",
"filter": true,
"inUse": true,
"editable": true,
"mandatory": true,
"priority": 0,
"textOptions": "a,b,c,d",
"type": "DATETIME_FORM_DATA",
"filterType": "ABSOLUTE",
"metaDataAttribute": {
"masked": true,
"maxLength": 200,
"formula": "a + b",
"parentCode": "strAttr_1",
"currency": "$"
}
}
I want to add metaDataAttribute when I hit Postman its giving internal server error:
argument "content" is null
failed to fetch attribute label mappings
argument "content" is null
at com.fasterxml.jackson.databind.ObjectMapper._assertNotNull(ObjectMapper.java:4693)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3401)
at in.nobroker.hood.crm.entity.HashMapConverter.convertToEntityAttribute(HashMapConverter.java:31)
at in.nobroker.hood.crm.entity.HashMapConverter.convertToEntityAttribute(HashMapConverter.java:10)
at org.hibernate.metamodel.model.convert.internal.JpaAttributeConverterImpl.toDomainValue(JpaAttributeConverterImpl.java:45)
at org.hibernate.type.descriptor.converter.AttributeConverterSqlTypeDescriptorAdapter$2.doConversion(AttributeConverterSqlTypeDescriptorAdapter.java:140)
... 186 common frames omitted
Add a null check on String s, in convertToEntityAttribute of HashMapConverter
I have the below test case with imports as
import org.springframework.http.MediaType;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.assertj.core.internal.bytebuddy.matcher.ElementMatchers.is;
import static org.mockito.Mockito.doReturn;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
#Test
#DisplayName("Should return product based on the specified Id")
void shouldReturnProductBasedOnTheSpecifiedId() throws Exception {
String Id = java.util.UUID.randomUUID().toString();
ProductViewModel productViewModel = new ProductViewModel(Id, "Product 1", 100, "Product 1 description", 0);
doReturn(productViewModel).when(productService).findById(Id);
mockMvc.perform(get(String.format("/api/v1/product/%s", Id)))
//Validate the response code and content type
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
//validate the headers
.andExpect(header().string(HttpHeaders.ETAG, String.format("\"%s\"", Id)))
.andExpect(header().string(HttpHeaders.LOCATION, String.format("/%s", Id)))
//Validate the return fields
.andExpect(jsonPath("$.id", is(Id)));
//.andExpect((ResultMatcher) jsonPath("$.name", is("Product 1")))
//.andExpect((ResultMatcher) jsonPath("$.price", is(100)))
//.andExpect((ResultMatcher) jsonPath("$.description", is("Product 1 description")))
//.andExpect((ResultMatcher) jsonPath("$.version", is(0)));
}
Getting an error as
If I cast the object I get an cast error message.
There are several ways to solve it:
Include individual Json properties comparison
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.http.MediaType.APPLICATION_JSON;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.hamcrest.core.Is.is;
mockMvc.perform(get(String.format("/api/v1/product/%s", Id))
.andExpect(content().contentType(APPLICATION_JSON_VALUE))
.andExpect(jsonPath("$.id", is(Id)));
The difference with your example is on "is import".
Deserialize Json response into a class and compare objects
This is a more generic and reusable approach.
Use a Json deserialize method to convert that one into an object of a well-known class instance.
Compare expected object with the received one in the test.
You can see a complete example of it in the following link, more specifically in the test:
static Stream<Arguments> findByIdWithOrderLines_validIdTestCases() {
PizzaDto pizzaDto = new PizzaDto((short)1, "Carbonara", 7.50);
OrderLineDto orderLineDto = new OrderLineDto(10, 1, pizzaDto, (short)2, 15D);
OrderDto dto = new OrderDto(1, "Order 1", new Date(), asList(orderLineDto));
return Stream.of(
//#formatter:off
// serviceResult, expectedResultHttpCode, expectedBodyResult
Arguments.of( empty(), NOT_FOUND, null ),
Arguments.of( of(dto), OK, dto )
); //#formatter:on
}
#ParameterizedTest
#SneakyThrows
#WithMockUser(authorities = {Constants.ROLE_ADMIN})
#MethodSource("findByIdWithOrderLines_validIdTestCases")
#DisplayName("findByIdWithOrderLines: when given Id verifies the validations then the suitable Http code is returned")
public void findByIdWithOrderLines_whenGivenIdVerifiesValidations_thenSuitableHttpCodeIsReturned(Optional<OrderDto> serviceResult,
HttpStatus expectedResultHttpCode, OrderDto expectedBodyResult) {
// Given
Integer validOrderId = 1;
// When
when(mockOrderService.findByIdWithOrderLines(validOrderId)).thenReturn(serviceResult);
ResultActions result = mockMvc.perform(get(RestRoutes.ORDER.ROOT + "/" + validOrderId + RestRoutes.ORDER.WITH_ORDERLINES));
// Then
result.andExpect(status().is(expectedResultHttpCode.value()));
assertEquals(expectedBodyResult, fromJson(result.andReturn().getResponse().getContentAsString(), OrderDto.class));
verify(mockOrderService, times(1)).findByIdWithOrderLines(validOrderId);
}
I have a service consumer who wants my service to produce line delimited JSONL. How can I modify the Jackson parser or provide a custom serializer so that a retuned array of objects is serialized as JSONL and not JSON.
For example the following code
import java.util.Arrays;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
#SpringBootApplication
#RestController
public class JsonlServiceApplication {
public static void main(String[] args) {
SpringApplication.run(JsonlServiceApplication.class, args);
}
#GetMapping("jsonl")
private ResponseEntity<?> getJsonl(){
Pair<String, String> p1 = Pair.of("foo", "baa");
Pair<String, Integer> p2 = Pair.of("key", 10);
return new ResponseEntity(Arrays.asList(p1, p2), HttpStatus.OK);
}
}
Will produce this JSON:
[
{
"foo": "baa"
},
{
"key": 10
}
]
But the consumer would like:
{"foo": "baa"}
{"key": 10}
Maybe you can parse your json into an Object[] and iterate on each elem ? like that :
public static void main(String[] args) {
String json = "[{\"foo\":\"baa\"},{\"key\":10}]";
Gson gson = new Gson();
Object yourObj[] = gson.fromJson(json, Object[].class);
Arrays.stream(yourObj).forEach(e -> {
System.out.println(e);
});
}
I've been writing a Rest service using Jackson to extract the name and sizeFromStorage inside the response value.
I created the below classes in an attempt to do this:
import java.util.List;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
#JsonIgnoreProperties(value = {"status", "header"})
public class Vaults {
private List<Object> response;
public Vaults(){
}
public Vaults(List<Object> response){
this.response = response;
}
public List<Object> getResponse(){
return response;
}
public void setResponse(List<Object> response) {
this.response = response;
}
#Override
public String toString() {
return "" + response;
}
}
import java.io.IOException;
import java.util.List;
import java.util.ArrayList;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.CollectionType;
import java.io.InputStream;
public class JacksonObjectModelTest {
public static void main(String[] args) throws IOException {
String jsonFileName = "/JsonRead/json.json";
List<Vaults> emps = new JacksonObjectModelTest().getVaultList(jsonFileName);
System.out.println(emps.toString());
}
public ArrayList<Vaults> getVaultList(String jsonFileName) throws IOException {
//read json file data to String
InputStream inputStream = getClass().getResourceAsStream(jsonFileName);
//create ObjectMapper instance
ObjectMapper objectMapper = new ObjectMapper().enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
//convert json string to object
CollectionType collectionType = objectMapper.getTypeFactory().constructCollectionType(List.class, Vaults.class);
ArrayList<Vaults> emps = objectMapper.readValue(inputStream, collectionType);
return (ArrayList<Vaults>) emps;
}
}
{
"status": "ok",
"header": {
"now": 1491545894581,
"status": "ok",
"requestId": "WOcvJsCoAmoAAESbkBYAAAB5"
},
"response": {
"vault": [
{
"id": 20,
"name": "Apple",
"description": "",
"sizeFromStorage": 95957225298,
"storagePools": [
{
"storagePool": {
"id": 1,
"name": "storage-pool1",
"sizeFromStorage": 95957225298,
"generations": [
{
"generation": {
"sequence": 0
}
}
]
}
}
]
},
{
"id": 21,
"name": "Banana",
"description": "",
"sizeFromStorage": 98957268244,
"storagePools": [
{
"storagePool": {
"id": 2,
"name": "storage-pool1",
"sizeFromStorage": 98957268244,
"generations": [
{
"generation": {
"sequence": 0
}
}
]
}
}
]
},
]
}
}
The output I get from this is:
[[{vaults=[{id=20, name=Apple, description=, sizeFromStorage=95957225298, storagePools=[{storagePool={id=1, name=storage-pool1, sizeFromStorage=5043, estimateUsableTotalLogicalSizeFromStorage=95957225298, generations=[{generation={sequence=0}}]}}]}, {id=20, name=Apple, description=, sizeFromStorage=95957225298, storagePools=[{storagePool={id=1, name=storage-pool1, sizeFromStorage=5043, estimateUsableTotalLogicalSizeFromStorage=95957225298, generations=[{generation={sequence=0}}]}}]}]]
However, what I want to do is the name and sizeFromStorage values. So far I've managed to strip out the first three values. Unfortunately I'm now stuck as I'm not very familiar with Rest services or reading JSON. Is there any way I can delve further into the JSON to get what I need or have I approached this in the wrong way?
Additional info:
Since posting my original question I came up with this(based on something I saw on a different site):
package JsonRead;
import java.io.File;
import java.io.IOException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
public class JacksonTreeModel {
public static void main(String[] args) {
try{
ObjectMapper mapper = new ObjectMapper();
JsonNode root = mapper.readTree(new File("JsonRead/json.json"));
JsonNode vaultsNode = root.path("response").path("vault");
/*if(vaultsNode.isArray()){
for(JsonNode node : vaultsNode){
String name = node.path("name").asText();
System.out.println("Array Name: " + name);
}
}*/
for(JsonNode node : vaultsNode){
String name = node.path("name").asText();
String bytesUsed = node.path("sizeFromStorage").asText();
System.out.println("Name: " + name + ", Bytes Used: " + bytesUsed);
}
} catch(IOException e){
System.out.println("IO Exception " + e );
}
}
}
It works for what I want but is there a better way to do this?
Will, thanks for the response. I'll look into your suggestion.
Ok, so i just re-read your question.
Recommend creating yourself a VaultDAO object with a more meaningful custom object type to use for the response collections. Prvoided you use the same variable names (which it looks like are known to you) then it should deserialize for you
I am very new to Rest api in java .My Question is how to directly convert json string request to java class object before post or get function ,like
json string : '{"id":3,"name":name}'
rest api post method :
#Post
public Something postData(Something obj) throws Exception {
}
so how to apply json serialization before request to this method.
right now i am converting it inside postData method.
You can use Jackson API to play with JSON.
For the Following JSON data the Java object mapping can be done as follows.
{
"id": 123,
"name": "Pankaj",
"permanent": true,
"address": {
"street": "Albany Dr",
"city": "San Jose",
"zipcode": 95129
},
"phoneNumbers": [
123456,
987654
],
"role": "Manager",
"cities": [
"Los Angeles",
"New York"
],
"properties": {
"age": "29 years",
"salary": "1000 USD"
}
}
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.journaldev.jackson.model.Address;
import com.journaldev.jackson.model.Employee;
public class JacksonObjectMapperExample {
public static void main(String[] args) throws IOException {
//read json file data to String
byte[] jsonData = Files.readAllBytes(Paths.get("employee.txt"));
//create ObjectMapper instance
ObjectMapper objectMapper = new ObjectMapper();
//convert json string to object
Employee emp = objectMapper.readValue(jsonData, Employee.class);
System.out.println("Employee Object\n"+emp);
//convert Object to json string
Employee emp1 = createEmployee();
//configure Object mapper for pretty print
objectMapper.configure(SerializationFeature.INDENT_OUTPUT, true);
//writing to console, can write to any output stream such as file
StringWriter stringEmp = new StringWriter();
objectMapper.writeValue(stringEmp, emp1);
System.out.println("Employee JSON is\n"+stringEmp);
}
public static Employee createEmployee() {
Employee emp = new Employee();
emp.setId(100);
emp.setName("David");
emp.setPermanent(false);
emp.setPhoneNumbers(new long[] { 123456, 987654 });
emp.setRole("Manager");
Address add = new Address();
add.setCity("Bangalore");
add.setStreet("BTM 1st Stage");
add.setZipcode(560100);
emp.setAddress(add);
List<String> cities = new ArrayList<String>();
cities.add("Los Angeles");
cities.add("New York");
emp.setCities(cities);
Map<String, String> props = new HashMap<String, String>();
props.put("salary", "1000 Rs");
props.put("age", "28 years");
emp.setProperties(props);
return emp;
}
}
Source : http://www.journaldev.com/2324/jackson-json-processing-api-in-java-example-tutorial
You can use Gson or do a manually serialization/deserialization using JSONObject/JSONArray classes (example here). There are many other ways/libs to do this.