I am writing test case for mapper method where new object instance is creating for mapping. How to mock all mapper objects and set in setter? Eclipse tool passing test but jacoco is giving 0% coverage on this code.
public class NewUseInsideMethods {
public StudentOldTestingReturn OldLogicTesting(StudentOldTesting Student) {
StudentOldTestingReturn sturentReturn = new StudentOldTestingReturn();
OldBatchName batchName = new OldBatchName();
batchName.setId("1");
batchName.setName("test");
sturentReturn.setId(batchName.getId());
sturentReturn.setName(Student.getName());
return sturentReturn;
}
}
public class OldBatchName {
private String name;
private String id;
//setter and getter
}
public class StudentOldTesting {
private String name;
private String id;
//setter and getter
}
public class StudentOldTestingReturn {
private String name;
private String id;
//setter and getter
}
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
#ExtendWith(MockitoExtension.class)
class NewUseInsideMethodsTest {
#Test
void OldLogicTesting() throws Exception {
StudentOldTesting oldTesting = new StudentOldTesting();
oldTesting.setName("shraban");
oldTesting.setId("1");
NewUseInsideMethods insideMethods = new NewUseInsideMethods();
StudentOldTestingReturn result = insideMethods.OldLogicTesting(oldTesting);
Assertions.assertNotNull(result);
Assertions.assertEquals("shraban", result.getName());
Assertions.assertEquals("1", result.getId());
}
}
Related
After enabling AfterburnerModule I am seeing the below warning message in the logs. Without AfterburnerModule everything works fine.
Sep 06, 2017 9:11:39 AM com.fasterxml.jackson.module.afterburner.deser.BeanPropertyMutator _reportProblem
WARNING: Disabling Afterburner deserialization for class com.test.Child (field #0; mutator com.test.Child$Access4JacksonDeserializerdc6e0fab), due to access error (type java.lang.IllegalAccessError, message=tried to access method com.test.test2.Parent.setSurname(Ljava/lang/String;)V from class com.test.Child$Access4JacksonDeserializerdc6e0fab)
java.lang.IllegalAccessError: tried to access method com.test.test2.Parent.setSurname(Ljava/lang/String;)V from class com.test.Child$Access4JacksonDeserializerdc6e0fab
at com.test.Child$Access4JacksonDeserializerdc6e0fab.stringSetter(com/test/Child$Access4JacksonDeserializer.java)
at com.fasterxml.jackson.module.afterburner.deser.BeanPropertyMutator.stringSetter(BeanPropertyMutator.java:123)
at com.fasterxml.jackson.module.afterburner.deser.SettableStringMethodProperty.deserializeAndSet(SettableStringMethodProperty.java:60)
at com.fasterxml.jackson.module.afterburner.deser.SuperSonicBeanDeserializer.deserialize(SuperSonicBeanDeserializer.java:156)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3807)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2797)
at com.test.JacksonStuff.main(JacksonStuff.java:19)
My class are as follows:
package com.test.test2;
import com.fasterxml.jackson.annotation.JsonProperty;
public class Parent {
#JsonProperty("surname")
private String surname;
protected Parent() {
}
public Parent(String surname) {
this.surname = surname;
}
public String getSurname() {
return surname;
}
protected void setSurname(String surname) {
this.surname = surname;
}}
package com.test;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.test.test2.Parent;
public class Child extends Parent {
#JsonProperty("name")
private String test;
public Child() {
super();
}
public Child(String var1) {
super(var1);
}
public String getTest() {
return test;
}
public void setTest(String test) {
this.test = test;
}}
package com.test;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.module.afterburner.AfterburnerModule;
import java.io.IOException;
public class JacksonStuff {
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
AfterburnerModule module = new AfterburnerModule();
mapper.registerModule(module);
String json = "{\"surname\":\"abc\"}";
Child value = mapper.readValue(json, Child.class);
}}
How do I avoid getting this warning in the logs? I cannot modify parent.java as it is from a third party lib and not under my control.
Because void setSurname is protected. Set it to public.
I'm just getting familiar with Jackson binding. However, when I'm testing setSerializationInclusion(JsonInclude.Include.NON_NULL), I found that it's not working sometimes.
Here is my code
package com.blithe.main;
import com.blithe.model.Student;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class Jackson_2_NullValue {
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
Student s = new Student();
String stundetString = mapper.writeValueAsString(s);
System.out.println(stundetString);
// exclude null fields
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
s.setName("ss");
stundetString = mapper.writeValueAsString(s);
System.out.println(stundetString);
}
}
and the POJO
package com.blithe.model;
import java.util.Date;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
// #JsonIgnoreProperties(ignoreUnknown = true)
// exclude null fields for the whole class
// #JsonInclude(Include.NON_NULL)
public class Student {
// exclude the field whe it's empty ("")
// #JsonInclude(value=Include.NON_EMPTY)
private String name;
private Integer age;
private Date birth;
// Jackson ignores it
#JsonIgnore
private String nickName;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
}
public String getNickName() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
}
the output is
{"name":null,"age":null,"birth":null}
{"name":"ss","age":null,"birth":null}
The later one should be null-value excluded, but it doesn't.
However, when I put my code this way.
package com.blithe.main;
import com.blithe.model.Student;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class Jackson_2_NullValue {
public static void main(String[] args) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
Student s = new Student();
String stundetString = mapper.writeValueAsString(s);
System.out.println(stundetString);
// exclude null fields
// mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
s.setName("ss");
stundetString = mapper.writeValueAsString(s);
System.out.println(stundetString);
}
}
It works with the output below
{}
{"name":"ss"}
Is this normal or just some kind of bug? Do I miss anything? The only maven dependency is jackson-databind 2.7.4. Any discussion is welcomed. Thanks!
Do not change ObjectMappers settings while using it. Once mapper has been in use not all settings take effect, because of caching of serializers and deserializers.
Configure an instance once and do not change settings after first use. It is done this way for thread-safety and performance.
Update: Dead links replaced with archive.org ones
http://wiki.fasterxml.com/JacksonFAQThreadSafety
http://wiki.fasterxml.com/JacksonBestPracticesPerformance
So the point is if you are using ObjectMappers at multiple places, try not to create objects again and again. it takes the configs of first initialized.
if you keep changing on a global level it will not work.
Java 1.8, Jackson library 2.1.5
I need to override the behaviour of how an object is serialized in json.
What i need is to ignore the bonus property from the serialized json response in case the value is null and the employee is a Partner employee. However trying the code below does not seem to work as expected.
class Employee{
private String bonus;
public String getBonus(){return bonus;}
public String setBonus(){this.bonus = bonus;}
}
class Partner extends Employee{
#Override
#JsonInclude(NON_NULL)
public String getBonus(){return super.getBonus();}
}
Any help?
If you can get by with excluding all null properties, then you can use the #JsonSerialize on the class. The following test runs successfully for me using Jackson 2.1.5:
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.junit.Test;
public class SomeTest {
public static class Employee {
private String bonus;
public String getBonus() {
return bonus;
}
public void setBonus(String bonus) {
this.bonus = bonus;
}
}
#JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
public static class Partner extends Employee {
#Override
public String getBonus() {
return super.getBonus();
}
}
#Test
public void testSerialize() throws Exception {
Employee employee = new Employee();
Partner partner = new Partner();
ObjectMapper objectMapper = new ObjectMapper();
System.out.println("Employee: " + objectMapper.writeValueAsString(employee));
System.out.println(" Partner: " + objectMapper.writeValueAsString(partner));
}
}
Output:
Employee: {"bonus":null}
Partner: {}
I have the follow json.
{
foo:{
id:1
},
name:'Albert',
age: 32
}
How can I deserialize to Java Pojo
public class User {
private int fooId;
private String name;
private int age;
}
This is what you need to deserialize, using the JsonProperty annotations in your constructor.
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
public class User {
private int fooId;
private String name;
private int age;
public int getFooId() {
return fooId;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public User(#JsonProperty("age") Integer age, #JsonProperty("name") String name,
#JsonProperty("foo") JsonNode foo) {
this.age = age;
this.name = name;
this.fooId = foo.path("id").asInt();
}
public static void main(String[] args) {
ObjectMapper objectMapper = new ObjectMapper();
String json = "{\"foo\":{\"id\":1}, \"name\":\"Albert\", \"age\": 32}" ;
try {
User user = objectMapper.readValue(json, User.class);
System.out.print("User fooId: " + user.getFooId());
} catch (IOException e) {
e.printStackTrace();
}
}
}
Output:
User fooId: 1
Hope it helps,
Jose Luis
You can do one of the following:
Create a concrete type representing Foo:
public class Foo {
private int id;
...
}
Then in User you would have:
public class User {
private Foo foo;
...
}
Use a Map<String, Integer>:
public class User {
private Map<String, Integer> foo;
...
}
If other callers are really expecting you to have a getFooId and a setFooId, you can still provide these methods and then either delegate to Foo or the Map depending on the option you choose. Just make sure that you annotate these with #JsonIgnore since they aren't real properties.
You can use a very helpful gson google API.
First of all, create these two classes:
User class:
public class User{
Foo foo;
String name;
int age;
//getters and setters
}
Foo class:
public class Foo{
int id;
//getters and setters
}
If you have a example.json file then deserialize it as follow
Gson gson = new Gson();
User data = gson.fromJson(new BufferedReader(new FileReader(
"example.json")), new TypeToken<User>() {
}.getType());
If you have a exampleJson String then deserialize it as follow
Gson gson = new Gson();
User data = gson.fromJson(exampleJson, User.class);
I read that it's useful to use builder pattern when you have a class with a lot of parameters. I wonder how you can implement an entity using builder pattern. It would be great if you can provide sample code.
Of course it is possible, you just have to provide a (possibly nested) Builder for every Entity.
Here is a working example:
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
#Entity
public class FluentEntity {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String someName;
private int someNumber;
private boolean someFlag;
protected FluentEntity(){}
private FluentEntity(String someName, int someNumber, boolean someFlag) {
this.someName = someName;
this.someNumber = someNumber;
this.someFlag = someFlag;
}
public long getId() {
return id;
}
public String getSomeName() {
return someName;
}
public int getSomeNumber() {
return someNumber;
}
public boolean isSomeFlag() {
return someFlag;
}
public static FluentEntityBuilder builder() {
return new FluentEntityBuilder();
}
public static class FluentEntityBuilder {
private String someName;
private int someNumber;
private boolean someFlag;
public FluentEntityBuilder setSomeName(final String someName) {
this.someName = someName;
return this;
}
public FluentEntityBuilder setSomeNumber(final int someNumber) {
this.someNumber = someNumber;
return this;
}
public FluentEntityBuilder setSomeFlag(final boolean someFlag) {
this.someFlag = someFlag;
return this;
}
public FluentEntity build() {
return new FluentEntity(someName, someNumber, someFlag);
}
}
}
The code to use it would be this:
FluentEntity entity = FluentEntity.builder().setSomeName(someName).setSomeNumber(someNumber)
.setSomeFlag(someFlag).build();
Just keep in mind that you have to exclude auto-generated fields like the primary key (in this example id) if you have some.
If you want to get rid of the "boilerplate" code for creating Builder classes for every Entity I would recommend a convenience library, something like Lombok. Then you will get your Builders (and even more) by just annotating your Entites, maybe it costs a little extra work to exclude the id fields.
You should take a look at Project Lombok
Nevertheless, here is some code to test this Builder (implemented with Spring Boot and Hibernate).
The repository:
import org.springframework.data.repository.CrudRepository;
import com.example.model.FluentEntity;
public interface FluentEntityRepository extends CrudRepository<FluentEntity, Long> {
}
And here are some tests:
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.greaterThan;
import java.util.stream.StreamSupport;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.transaction.annotation.Transactional;
import com.example.model.FluentEntity;
#RunWith(SpringRunner.class)
#Transactional
#SpringBootTest
public class FluentEntityRepositoryTests {
#Autowired
private FluentEntityRepository fluentEntityRepository;
#Test
public void insertAndReceiveFluentEntityCreatedWithBuilder() {
final String someName = "name";
final int someNumber = 1;
final boolean someFlag = true;
FluentEntity entity = FluentEntity.builder().setSomeName(someName).setSomeNumber(someNumber)
.setSomeFlag(someFlag).build();
entity = fluentEntityRepository.save(entity);
assertThat("Entity did not get a generated Id!", entity.getId(), greaterThan(-1L));
assertThat("Entity name did not match!", entity.getSomeName(), is(someName));
assertThat("Entity number did not match!", entity.getSomeNumber(), is(someNumber));
assertThat("Entity flag did not match!", entity.isSomeFlag(), is(someFlag));
}
#Test
public void insertSomeAndReceiveFirst() {
fluentEntityRepository.save(FluentEntity.builder().setSomeName("A").setSomeNumber(1).setSomeFlag(true).build());
fluentEntityRepository
.save(FluentEntity.builder().setSomeName("B").setSomeNumber(2).setSomeFlag(false).build());
fluentEntityRepository.save(FluentEntity.builder().setSomeName("C").setSomeNumber(3).setSomeFlag(true).build());
final Iterable<FluentEntity> findAll = fluentEntityRepository.findAll();
assertThat("Should get some iterable!", findAll, notNullValue());
final FluentEntity fluentEntity = StreamSupport.stream(findAll.spliterator(), false).findFirst().get();
assertThat("Should get some entity!", fluentEntity, notNullValue());
}
}