Orika - How can I map abstract nested property's fields - java

Hi I'm having a hard time mapping an abstract nested property's fields. Here I have the test case that explains it better:
package com.mycompany.asd;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import ma.glasnost.orika.MapperFactory;
import ma.glasnost.orika.MappingException;
import ma.glasnost.orika.impl.DefaultMapperFactory;
/**
* Tests the mapping of abstract nested property's fields
*/
public class OrikaTest {
private MapperFactory mapperFactory;
#Before
public void createMapperFactoryAndDefineMapping() {
mapperFactory = new DefaultMapperFactory.Builder()
.useAutoMapping(false).build();
mapperFactory.classMap(FakeBeanA.class, FakeBeanB.class)
.field("fieldA", "fieldB.nestedField")
.field("fieldA2", "fieldB.nestedField2") // Problem here.
.register();
}
#Test(expected = MappingException.class)
public void cannotMapAbstractNestedPropertyWhenConcreteTypeIsNotRegistered() {
// We expect to get a MappingException. Indeed, Orika doesn't know how
// to create an
// instance of AbstractNestedField (the type of FakeBeanB.fieldB)
createAnInstanceOfFakeBeanAAndMapItToFakeBeanB();
}
#Test
public void mapAbstractNestedPropertyWhenConcreteTypeIsRegistered() {
// Register concrete type for AbstractNestedType
mapperFactory.registerConcreteType(AbstractNestedType.class,
NestedType.class);
// Orika should be able to create an instance of FieldB abstract type
// (as we have explicitly defined above the concrete type to create and
// the SimpleConstructorResolverStrategy is normally able to create an
// instance of this concrete type)
// Therefore, the mapping should work !
createAnInstanceOfFakeBeanAAndMapItToFakeBeanB();
}
private void createAnInstanceOfFakeBeanAAndMapItToFakeBeanB() {
// Create an instance of FakeBeanA and assign a value to its fieldA
FakeBeanA fakeBeanA = new FakeBeanA();
fakeBeanA.fieldA = 42;
// Try the mapping from fakeBeanA to FakeBeanB
FakeBeanB fakeBeanB = mapperFactory.getMapperFacade().map(fakeBeanA,
FakeBeanB.class);
// Assert the fieldA has been correctly mapped to fieldB.nestedField
Assert.assertEquals(fakeBeanA.fieldA, fakeBeanB.fieldB.nestedField);
}
public static class FakeBeanA {
public int fieldA;
public int fieldA2;
}
public static class FakeBeanB {
public AbstractNestedType fieldB;
}
public static class NestedType extends AbstractNestedType {
public int nestedField2; // NEW ADDED
}
public static abstract class AbstractNestedType {
public int nestedField;
}
}

This is not possible, and does not make sense, what if there is another subclass of AbstractNestedType that does not have nestedField2 ?
What you can do is to use
.customize(new CustomMapper<> {
void mapBToA(FakeBeanA a, FakeBeanB b) {
if(b.fieldB instanceof NestedType) {
a.fieldA2 = ((NestedType)b.fieldB).nestedField2;
}
}});
...

Related

Java Mockit : How to Mock a generic class method in JMockit

Hi I have the following classes
public class DataAccessLayer<T> {
public T getData(Class<?> dataInfoType ,Integer id){
//Some logic here
}
}
public class ServiceLayer{
//this method has to be tested
public Integer testingMethode{
//The following line should be mocked
UtilClass info = new DataAccessLayer<UtilClass>().getData(UtilClass.class, 1);
retutn info.getSomeFieldWithIntegerValue();
}
}
I want to write test cases for testingMethode for that I need to mock the getData() method in DataAccessLayer<T>
Is it possible with jmockit to mock a Template(Generic ) class?
A generic class can be mocked the same way a non-generic one:
#Test
public void example(#Mocked final DataAccessLayer<UtilClass> mock)
{
final UtilClass data = new UtilClass(123);
new Expectations() {{ mock.getData(UtilClass.class, 1); result = data; }};
int result = new ServiceLayer().testingMethode();
assertEquals(123, result);
}
(I can only really answer for Mockito, as that is what I am most familiar with; but the same principle should be applicable in other mocking frameworks).
Firstly, you need to be able to inject a DataAccessLayer<UtilClass> into ServiceLayer, e.g.
class ServiceLayer {
private final DataAccessLayer<UtilClass> dal;
ServiceLayer(DataAccessLayer<UtilClass> dal) {
this.dal = dal;
}
public Integer testingMethode() {
UtilClass info = dal.getData(UtilClass.class, 1);
return info.getSomeFieldWithIntegerValue();
}
}
This breaks the static coupling to the DataAccessLayer<UtilClass> created by the use of the new.
Now, you can create a mocked instance of DataAccessLayer<UtilClass> by creating a non-generic subclass:
class UtilClassDataAccessLayer extends DataAccessLayer<UtilClass> {}
and then create a mock instance:
DataAccessLayer<UtilClass> mocked = mock(UtilClassDataAccessLayer.class);
Now, you can configure this mock as you need, and pass it into the ServiceLayer:
ServiceLayer serviceLayer = new ServiceLayer(mocked);
In JMockit there's actually no need to create a holding variable in the ServiceLayer class, nor is there a need to make a parameterized subclass of your DataLayer. The following test works just fine:
package com.example.dsohl;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
import org.junit.Test;
import org.junit.runner.RunWith;
import mockit.Deencapsulation;
import mockit.Expectations;
import mockit.Mocked;
import mockit.Tested;
import mockit.integration.junit4.JMockit;
#RunWith(JMockit.class)
public class TestTest {
public static class UtilClass {
public Integer foo() {
return 5;
}
}
public static class DataLayer<T> {
public T getItem(Class<T> clazz, int itemId) {
return null;
}
}
public static class ServiceLayer {
public Integer testMethod() {
UtilClass util = new DataLayer<UtilClass>().getItem(UtilClass.class, 1);
return util.foo();
}
}
// Test really begins here
#Tested ServiceLayer svc;
#Mocked DataLayer<UtilClass> data;
#Mocked UtilClass util;
#Test
public void testDateSubtraction() throws Exception {
new Expectations() {
{
new DataLayer<UtilClass>(); result = data;
onInstance(data).getItem(UtilClass.class, 1); result = util;
util.foo(); result = 37;
}
};
Integer i = svc.testMethod();
assertThat(i, equalTo(37));
}
}
A few notes: First, my DataLayer.getItem() returns null so if the injection fails, we get a NullPointerException, nice and obvious. Obviously your code won't work like this; this is only to convince you.
Second, I use onInstance() so that we can be 100% certain that the result of the DataLayer constructor is what we are using in the next steps of the test. The default behaviour of Expectations on a #Mocked object is to record the expectation against any object of that class; this is how we are certain that it's our object that's being used. (Ordinarily I don't worry myself about this, but when using new I like to be certain.)
Finally, I'm omitting some other stuff I might do in cases like this, like use a Verifications block, etc. Just trying to be as straightforward as possible.
Enjoy!

Jackson prefers private constructor over #JsonCreator when deserializing a class with #JsonValue

I have a simple class with a private constructor and a static factory. I want the class to serialize as a number, so I've annotated the getter for the field with #JsonValue. However, Jackson appears to prefer the private constructor over the static factory, even when I annotate the static factory with #JsonCreator. It works if I annotate the private constructor with #JsonIgnore, but that feels a bit off.
I've seen some posts claiming that #JsonCreator only works if the parameters are annotated with #JsonProperty; however, that seems to be the case for objects serialized as JSON objects. This object is being serialized as a number, and thus there is no property to supply to the annotation.
Is there something I'm missing?
example class:
package com.example;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import com.google.common.base.Preconditions;
public class NonNegative {
private final double n;
private NonNegative(double n) {
this.n = n;
}
#JsonCreator
public static NonNegative checked(double n) {
Preconditions.checkArgument(n >= 0.0);
return new NonNegative(n);
}
#JsonValue
public double getValue() {
return n;
}
#Override
public int hashCode() {
return Objects.hash(n);
}
#Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof NonNegative) {
NonNegative that = (NonNegative) obj;
return Objects.equals(n, that.n);
}
return false;
}
}
example tests:
package com.example;
import static org.assertj.core.api.Assertions.assertThat;
import org.junit.Test;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class NonNegativeTest {
private static final ObjectMapper MAPPER = new ObjectMapper();
#Test
public void itSerializesAndDeserializes() throws Exception {
NonNegative nonNegative = NonNegative.checked(0.5);
assertThat(MAPPER.readValue(MAPPER.writeValueAsString(nonNegative), NonNegative.class)).isEqualTo(nonNegative);
}
/* This test fails. */
#Test(expected = JsonMappingException.class)
public void itDoesNotDeserializeANegativeNumber() throws Exception {
MAPPER.readValue(MAPPER.writeValueAsString(-0.5), NonNegative.class);
}
}
Indeed Jackson will override JsonCreator method with constructor method in case if parameter is Java standard type. I would say this is a bug in BasicDeserializerFactory#_handleSingleArgumentConstructor method.
So, the problem is that constructor has higher priority then static factory method in case if that constructor and static factory method has regular Java type. There is few ways how to workaround it.
Set creator visibility level to NON_PRIVATE:
#JsonAutoDetect(creatorVisibility = JsonAutoDetect.Visibility.NON_PRIVATE)
class NonNegative {
Second way is to delete static factory method and use constructor. I moved Preconditions.checkArgument to the constructor (it doesn't do much... Just throw an IllegalArgumentException if condition is not satisfied):
public class NonNegative {
private final double n;
private NonNegative(double n) {
Preconditions.checkArgument(n >= 0.0);
this.n = n;
}
#JsonValue
public double getValue() {
return n;
}
}
Another way is to use #JsonIgnore annotation but you mention that you don't like this approach :)
Update I've logged a bug: https://github.com/FasterXML/jackson-databind/issues/660
Update Jackson bug that prefers constructor over static factory method was resolved: https://github.com/FasterXML/jackson-databind/commit/257ae1c7a88c5ccec2882433a39c0df1de2b73aa

In testing in java how to check if a method of an interface is called or not?

I want to test this class which calls a method of interface using anonymous class.
public class ClassToTest
{
public void methodToTest()
{
InterefaceToMock interefaceToMockReference = new InterefaceToMock() {
#Override
public int methodToMock()
{
return 0;
}
};
interefaceToMockReference.methodToMock();
}
}
This is the interface
public interface InterefaceToMock
{
public int methodToMock();
}
I am using this approch to check it methodToMock is called or not
import static org.junit.Assert.*;
import org.junit.Test;
import mockit.FullVerificationsInOrder;
import mockit.Mocked;
import mockit.NonStrictExpectations;
public class TestAClass
{
#Mocked InterefaceToMock interefaceToMockReferenceMocked;
#Test
public void test1()
{
new NonStrictExpectations()
{
{
interefaceToMockReferenceMocked.methodToMock();times=1;
}
};
(new ClassToTest()).methodToTest();
new FullVerificationsInOrder(interefaceToMockReferenceMocked)
{
};
assertTrue(true);
}
}
But test case fails.
Can anyone help.
Your original test was almost correct. It declared the mock field as simply being #Mocked, which merely gives you a single mocked instance implementing the interface, and this is not the one used by the code under test. The JMockit API has another mocking annotation, however, which extends mocking to all implementation classes from a given base type, and by default affects all instances of said classes. So, the test should be changed as follows:
public class TestAClass
{
#Capturing InterfaceToMock anyImplementingInstance;
#Test
public void test1()
{
new ClassToTest().methodToTest();
new Verifications() {{
anyImplementingInstance.methodToMock();
}};
}
}
In the general case, if you have an class and you want to check whether a method on a Mock of that class is called, you use Mockito.verify.
For example:
public class AppTest {
#Test
public void testMe() {
final ITest iTest = Mockito.mock(ITest.class);
final CUT cut = new CUT(iTest);
cut.doStuff();
Mockito.verify(iTest).someStuff();
}
interface ITest {
void someStuff();
}
class CUT {
private final ITest iTest;
CUT(ITest iTest) {
this.iTest = iTest;
}
public void doStuff() {
iTest.someStuff();
}
}
}
Here, the test is whether ITest.someStuff() is called from CUT.doStuff().
Your example is undecipherable...

#XmlJavaTypeAdapter is ignored in same cases

I'm using the Class AdapterDataObj to convert the Class DataObj to AdaptedDataObj, when JAXB.marshal is called.
package test;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
#XmlJavaTypeAdapter(AdapterDataObj.class)
public class DataObj {
public String bla = "I'm DataObj";
public String name;
public DataObj(String name) {
this.name = name;
}
}
package test;
public class AdaptedDataObj {
public String bla="I'm AdaptedDataObj";
public String name;
public AdaptedDataObj(String name) {
this.name = name;
}
}
package test;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class AdapterDataObj extends XmlAdapter {
#Override
public DataObj unmarshal(AdaptedDataObj v) throws Exception {
return null; // not needed in this case
}
#Override
public AdaptedDataObj marshal(DataObj v) throws Exception {
System.out.println("Marschal for " + v.name + " called!");
return new AdaptedDataObj(v.name);
}
}
Now I put the DataObj into a new Class and JAXB.marshal is called for this class. The output looks fine. I also get the message that AdaptedDataObj is called.
package test;
import javax.xml.bind.JAXB;
public class Testobj {
public DataObj x;
public Testobj() {
x = new DataObj("Hallo World");
}
public static void main(String[] args) throws Exception {
System.out.println("Testobj");
System.out.println("=================================");
Testobj to = new Testobj();
JAXB.marshal(to, System.out);
}
}
Now I change "public DataObj x;" to "public Object x;", because I want to store not only DataObj in that class.
But in this case the AdapterDataObj is not longer called. The DataObj and not the AdapterDataObj is exported as xml.
Any idea where the problem is?
I also tried without succes to add #XmlJavaTypeAdapter to the package-info.java. AdapterDataObj is still not called. I've tested with Java 1.7.0_45 and 1.8.0-ea.
package test;
import javax.xml.bind.JAXB;
import javax.xml.bind.annotation.XmlSeeAlso;
#XmlSeeAlso({DataObj.class})
public class Testobj3 {
public Object x;
public Testobj3() {
x = new DataObj("Hallo World");
}
public static void main(String[] args) throws Exception {
System.out.println("Testobj3");
System.out.println("=================================");
Testobj3 to3 = new Testobj3();
JAXB.marshal(to3, System.out);
}
}
According to JAXB 2.2 specification:
A #XmlJavaTypeAdapter that extends XmlAdapter and is specified on the class, interface or Enum type (i.e. on a
program element that matches meta annotation #Target={type}) must adapt
boundType at the point of reference as follows:
a property/field whose reference type is boundType
a property/field where boundType is used as a parametric type
So the field/property must be of given type in order to JAXB recognize that Adapter needs to be used.
For the same reason you cannot use adapters on root elements. The explanation can be found in closed JAXB issue JAXB-117:
Adapters are defined against types, not instances. In
particular, the adapter is designed in such a way that it's not always possible
to infer the right adapter just from an instance.
EDIT
Using Object in JAXB classes is not very common. Maybe the objects you want to store have something in common, so that you can extract interface/base class that you can annotate with #XmlJavaTypeAdapter. If they don't have anything in common maybe it would be better to store them as separate properties.

Innerclass sharing attribute information

I have a class called ContentStream... the problem is that the inner class AddRectancle suppose to get the info of the getter of the class GraphicBeginn...I thought the class ContentStream can reach the getter at least as the getter is public ... plse tell me how to
public class ContentStreamExt extends ContentStreamProcessor
{
private Matrix graphicalMatrix;
public ContentStreamProcessorExt(ExtListener extListener)
{
super(extListener);
}
private void enhanceAdditional()
{
GraphicBeginn beginnGraphic = new GraphicBeginn();
super.register("a", beginnGraphic);
super.register("b", new AddRectangle(beginnGraphic));
}
private static class AddRectangle(GrapicBeginn beginn)
{
// should get the info of uUx and uUy
}
private static class GraphicBeginn implements ContentOperator
{
private float uUx;
private float uUy;
public float getuUx()
{
return this.uUx;
}
public float getuUy()
{
return this.uUy;
}
..... // the input for uUx and uuy will be created in a method
}
The code you gave has a number of problems, it doesn't compile correctly as another poster has noted. It also appears you are providing a method signature while also declaring a class called "AddRectange". Is this a class or a method? You need to decide which, it can't be both. Here is an example that I think illustrates what you're trying to do in a general sense:
public class SampleClass {
public SampleClass() {
}
private void sampleClassMethod() {
A a = new A();
a.acceptB(new B());
}
private class A {
public void acceptB(B bObject) {
System.out.println(bObject.memberVar1);
}
}
private class B {
private int memberVar1 = 5;
}
}
If i understand your question correctly, The add rectangle class should be passed an instance of graphic begin on which it can invoke the public getters. This wiring can be done by the content stream class.
By the way the following is syntactically invalid
private static class AddRectangle(GrapicBeginn beginn)

Categories