Mocking method with final arguments - java

I have some method which use final String arguments in ServiceClassA.
#Service
public class ServiceClassA {
public String callingMethod(final String argOne, final String argTwo) {
//Implementation here
}
}
And its call within another method in another class ServiceClassB.
#Service
public class ServiceClassB {
private final ServiceClassA serviceClassA;
public MyResponse methodB() {
String inputOne = "111";
String inputTwo = MyEnum.AAA.getDescription();
final String result = serviceClassA.callingMethod(inputOne,inputTwo);
//some implementations
MyResponse response = new MyResponse();
//set values to response
return response;
}
}
Also there is a enum.
public enum MyEnum {
AAA(1, "AAA"), BBB(2,"BBB");
private static final Map<Integer, MyEnum> MYENUM_MAP = new HashMap<>();
static {
for (MyEnum myEnum : values()) {
MYENUM_MAP.put(myEnum.getValue(), myEnum);
}
}
private final int value;
private final String description;
private MyEnum(int value, String description) {
this.value = value;
this.description = description;
}
public String getDescription() {
return description;
}
public int getValue() {
return value;
}
}
I'm testing ServiceClassB using mockito and JUnit. When I try to mock callingMethod in ServiceClassA it returns null instead of the "SUCCESS".
#RunWith(MockitoJUnitRunner.class)
public class ServiceClassBTest {
#InjectMocks
private ServiceClassB serviceClassB;
#Mock
private ServiceClassA serviceClassA;
#Before
public void init() {
MockitoAnnotations.initMocks(this);
}
#Test
public void methodB_success(){
String result = "SUCCESS";
when(serviceClassA.callingMethod(Mockito.anyString(), Mockito.anyString())).thenReturn(result);
}
}
I tried several ways as below and always it returns null. But I want to get SUCCESS as the result.
when(myService.callingMethod(Mockito.anyString(), Mockito.anyString())).thenReturn(result); //return null
when(myService.callingMethod(Mockito.any(), Mockito.any())).thenReturn(result); //return null
when(myService.callingMethod(ArgumentMatchers.anyString(), ArgumentMatchers.anyString())).thenReturn(result); //return null
doReturn(result).when(myService).callingMethod(Mockito.anyString(), Mockito.anyString()); //return null

The problem there is that you are using #RunWith(MockitoJUnitRunner.class) together with MockitoAnnotations.initMocks(this). They are conflicting.
Use something one MockitoJUnitRunner or MockitoAnnotations.initMocks.
MockitoJUnitRunner Initializes mocks annotated with Mock, so that
explicit usage of MockitoAnnotations.initMocks(Object) is not
necessary. Mocks are initialized before each test method.
Working test:
#RunWith(MockitoJUnitRunner.class)
public class ServiceClassBTest {
#InjectMocks
private ServiceClassB serviceClassB;
#Mock
private ServiceClassA serviceClassA;
#Test
public void methodB_success(){
String result = "SUCCESS";
when(serviceClassA.callingMethod(Mockito.anyString(), Mockito.anyString())).thenReturn(result);
serviceClassB.methodB();
}
}

Related

Can Jackson automatically treat any constructor parameter as a JsonProperty?

How do I get Jackson to treat 'name' as if it had a #JsonProperty annotation?
public class SimpleClass {
private String name;
private String doNotSerialize;
public SimpleClass( #JsonProperty("name") String name ) {
this.name = name;
}
public String getName() {
return name;
}
public int getSum() {
return 1+1;
}
}
The way it is now, I get an error, Unrecognized field "sum", because it treats every getter as a serializable property.
If I add a class annotation:
#JsonAutoDetect( getterVisibility = JsonAutoDetect.Visibility.NONE )
I get an empty string when serializing. I was hoping that Jackson would see the #JsonProperty on the constructor parameter and figure it out.
If I change the class annotation to:
#JsonAutoDetect( getterVisibility = JsonAutoDetect.Visibility.NONE, fieldVisibility = JsonAutoDetect.Visibility.ANY )
Then I get the 'doNotSerialize' field included.
If I set a #JsonCreator on the constructor, and change my autodetect, I still get a blank string:
#JsonAutoDetect( getterVisibility = JsonAutoDetect.Visibility.NONE, fieldVisibility = JsonAutoDetect.Visibility.NONE, creatorVisibility = JsonAutoDetect.Visibility.ANY )
public class SimpleClass {
private String name;
private String doNotSerialize;
#JsonCreator
public SimpleClass( #JsonProperty("name") String name ) {
this.name = name;
}
public String getName() {
return name;
}
public int getSum() {
return 1+1;
}
}
What I'm hoping is that somehow I can tell Jackson to treat all the constructor parameters as serializable fields, and all other fields / setters as non-serializable.
You can use a filter to only serialise getters which have a matching field, e.g.
package org.example;
import com.fasterxml.jackson.annotation.JsonFilter;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ser.BeanPropertyWriter;
import com.fasterxml.jackson.databind.ser.PropertyWriter;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
import java.io.IOException;
import java.io.StringWriter;
public class App {
#JsonFilter("test")
public static class SimpleClass {
private String name;
private String doNotSerialize;
public SimpleClass(String name ) {
this.name = name;
}
public String getName() {
return name;
}
public int getSum() {
return 1+1;
}
}
public static void main( String[] args ) throws IOException {
SimpleFilterProvider filterProvider = new SimpleFilterProvider();
filterProvider.addFilter("test", new SimpleBeanPropertyFilter() {
#Override
protected boolean include(BeanPropertyWriter writer) {
return super.include(writer);
}
#Override
protected boolean include(PropertyWriter writer) {
String name = writer.getName();
Class clazz = writer.getMember().getDeclaringClass();
try {
clazz.getDeclaredField(name);
return super.include(writer);
} catch (NoSuchFieldException e) {
// ignore
return false;
}
}
});
ObjectMapper mapper = new ObjectMapper();
mapper.setFilterProvider(filterProvider);
StringWriter sw = new StringWriter();
mapper.createGenerator(sw).writeObject(new SimpleClass("foo"));
System.out.println(sw.toString());
}
}
I don't know your full requirements, but this should be a start.
I haven't tried to do what you actually, asked, that is, look at constructor parameters, but that should be possible too.
If you want "sum" to be included in the serializad json but want to ignore it when deserializing you can do:
#JsonIgnoreProperties(ignoreUnknown=true)
public class SimpleClass {
// properties/getters
public int getSum() { return 1+1; }
}
If you want to remove "sum" entirely from the json you can do
#JsonIgnoreProperties({"sum"})
public class SimpleClass {
// properties/getters
public int getSum() { return 1+1; }
}
or
public class SimpleClass {
// properties/getters
#JsonIgnore
public int getSum() { return 1+1; }
}

#Inject Annotation of 2 constructors for 2 dependent classes in Java

Here is the code I am trying :
public class ClassA {
private final String check;
private final ClassB classB;
//ClassA constructor
#Inject
public ClassA(String check, ClassB classB) {
this.check = check + "A";
this.classB = classB;
}
public String getCheck() {
String check = classB.getCheck();
print(check) ///////////////return checkA
}
}
public class ClassB {
private final String check;
//ClassB constructor
#Inject
public ClassB(String check) {
this.check = check + "B";
}
public String getCheck() {
return check;
}
}
So, when #Inject is annotated for both the constructors, classB.getCheck(); should return checkB but it returns checkA. I assume this is because the classB constructor is not being executed due to #Inject annotations. But I am not sure of the exact reason. Any suggestion what I am missing?

is this the right way to make builder pattern in real software environment? in short what is the best way to create builder pattern in java

is this the right way to create builder pattern in java, if not what could be possible changes.
tried with static class
public class Multiverse {
private UUID universeId;
private String universeName;
private String universeType;
private Boolean humanExistence;
public Boolean getHumanExistence() {
return humanExistence;
}
private Multiverse() {
throw new IllegalStateException("Can`t create object from constructor: try using builder");
}
private Multiverse(UUID universeId, String universeName, String universeType, Boolean humanExistence) {
super();
this.universeId = universeId;
this.universeName = universeName;
this.universeType = universeType;
this.humanExistence = humanExistence;
}
public static class MultiverseBuilder{
private UUID universeId;
private String universeName;
private String universeType;
private Boolean humanExistence;
public MultiverseBuilder makeUUId(UUID uuid) {
this.universeId=uuid;
return this;
}
public MultiverseBuilder createUniverse(String univ) {
this.universeName=univ;
return this;
}
public MultiverseBuilder setUniverseType(String universeType ) {
this.universeType=universeType;
return this;
}
public MultiverseBuilder isHumanExists(Boolean humanExistence) {
this.humanExistence=humanExistence;
return this;
}
public Multiverse build() {
return new Multiverse(universeId,universeName,universeType,humanExistence);
}
}
public UUID getUniverseId() {
return universeId;
}
public String getUniverseName() {
return universeName;
}
public String getUniverseType() {
return universeType;
}
}
Junit5 test
public class AssertionsTest6 {
private static Logger logger=Logger.getLogger(AssertionsTest6.class.getName());
Multiverse multiverse;
#BeforeEach
void init(){
multiverse=new Multiverse.MultiverseBuilder()
.makeUUId(UUID.randomUUID())
.createUniverse("Earth")
.setUniverseType("Big Bang")
.isHumanExists(true)
.build();
}
#Test
#DisplayName("Builder Testing")
void TestBuilder() {
assertEquals("Big Bang", multiverse.getUniverseType(), "test failed");
logger.info("Builder testing");
}
}
blocked reflection to make object directly from Multiverse class by doing this
private Multiverse() {
throw new IllegalStateException("Can`t create object from constructor: try using builder");
}
expected and actual are same. but not sure is this the best way to achieve objective. please correct or suggest me on this, [ expert advice required ]
Design considerations:
force usage of builder (no direct instance creation allowed)?
immutability (what happens when invoking setters on builder after an instance has been created)?
reusability: allow builder to create multiple instances?
Example for a non-reusable builder which can be used to create exactly one instance, which is effectively immutable:
public class Multiverse {
private UUID universeId;
private String universeName;
private String universeType;
private Boolean humanExistence;
private Multiverse() {
}
public UUID getUniverseId() {
return universeId;
}
public String getUniverseName() {
return universeName;
}
public String getUniverseType() {
return universeType;
}
public Boolean getHumanExistence() {
return humanExistence;
}
public static Builder aMultiverse() {
return new Builder();
}
public static class Builder {
private final Multiverse instance = new Multiverse();
private boolean consumed;
private Builder set(Consumer<Multiverse> access) {
if (consumed) {
throw new IllegalStateException("already consumed");
}
access.accept(instance);
return this;
}
public Builder universeId(UUID universeId) {
return set(x -> x.universeId = universeId);
}
public Builder universeName(String universeName) {
return set(x -> x.universeName = universeName);
}
public Builder universeType(String universeType) {
return set(x -> x.universeType = universeType);
}
public Builder humanExistence(Boolean humanExistence) {
return set(x -> x.humanExistence = humanExistence);
}
public Multiverse build() {
consumed = true;
return instance;
}
}
}
The aMultiVerse() naming convention for accessing the builder allows static import of the builder factory method without clashing with other builder factory methods:
Multiverse multiverse = aMultiverse()
.universeId(UUID.randomUUID())
.universeName("Earth")
.universeType("Big Bang")
.humanExistence(true)
.build();
Some notes about your approach:
I don't think that it makes any sense to 'block' users from creating an instance via reflection. Since you defined a constructor there is no no-arg constructor anyways. Thus instances can only be created by passing a builder.
I like to pass the builder instance to the constructor. This way you will have readable code even if the class has a lot of fields.
I like to call my builder just Builder. It's a nested class und you will probably always write Multiverse.Builder.
I like the actual class to have a factory method for the builder so I can just write Multiverse.builder() and start populating the fields.
The methods of the builder class should have a consistent naming scheme.
This is how my builders usually look like:
public class Multiverse {
private final UUID universeId;
private final String universeName;
private final String universeType;
private final Boolean humanExistence;
private Multiverse(Builder builder) {
this.universeId = builder.universeId;
this.universeName = builder.universeName;
this.universeType = builder.universeType;
this.humanExistence = builder.humanExistence;
}
public static Builder builder() {
return new Builder();
}
public UUID getUniverseId() {
return universeId;
}
public String getUniverseName() {
return universeName;
}
public String getUniverseType() {
return universeType;
}
public Boolean getHumanExistence() {
return humanExistence;
}
public Builder toBuilder() {
return new Builder(this);
}
public static class Builder {
private UUID universeId;
private String universeName;
private String universeType;
private Boolean humanExistence;
private Builder() {}
private Builder(Multiverse multiverse) {
this.universeId = multiverse.universeId;
this.universeName = multiverse.universeName;
this.universeType = multiverse.universeType;
this.humanExistence = multiverse.humanExistence;
}
public Builder withUniverseId(UUID universeId) {
this.universeId = universeId;
return this;
}
public Builder withUniverseName(String universeName) {
this.universeName = universeName;
return this;
}
public Builder withUniverseType(String universeType) {
this.universeType = universeType;
return this;
}
public Builder withHumanExistence(Boolean humanExistence) {
this.humanExistence = humanExistence;
return this;
}
public Multiverse build() {
return new Multiverse(this);
}
}
}
Creating multiverses works like this:
Multiverse multiverse1 = Multiverse.builder()
.withUniverseId(UUID.fromString("550e8400-e29b-11d4-a716-446655440000"))
.withUniverseName("my first multiverse")
.withUniverseType("type a")
.withHumanExistence(true)
.build();
If you decide to edit this multiverse later, you can do it like this:
Multiverse multiverse2 = multiverse1.toBuilder()
.withUniverseId(UUID.fromString("759e947a-7492-af67-87bd-87de9e7f5e95"))
.withUniverseName("my second multiverse")
.build();
This would fulfill the following assertions:
assert multiverse1.getUniverseId().equals("550e8400-e29b-11d4-a716-446655440000");
assert multiverse1.getUniverseName().equals("my first multiverse");
assert multiverse1.getUniverseType.equals("type a");
assert multiverse1.getHumanExistence == true;
assert multiverse2.getUniverseId().equals("759e947a-7492-af67-87bd-87de9e7f5e95");
assert multiverse2.getUniverseName().equals("my second multiverse");
assert multiverse2.getUniverseType.equals("type a");
assert multiverse2.getHumanExistence == true;
this is the final solution i think , Thank you #stevecross
public final class BootServer { // step #1 make class and fields final
private final Integer port;
private final String serverName;
private final String serverType;
private final String listenerType;
private BootServer(Builder builder) {// step #2 create private constructor
this.port = builder.port;
this.serverName = builder.serverName;
this.serverType = builder.serverType;
this.listenerType=builder.listenerType;
}
public static Builder builder() {//Step#3 create static builder method to return Builder
return new Builder();
}
public static final class Builder {//Step#4 create public static builder class
private Integer port;
private String serverName;
private String serverType;
private String listenerType;
private Builder(){
}
public BootServer build() {//Step#5 create build method to return BootServer Object with this object
return new BootServer(this);
}
public Builder addServerPort(Integer port) {//Step#6 finally create all build method to set values to main class
this.port=port;
return this;
}
public Builder addServerName(String name) {
this.serverName=name;
return this;
}
public Builder setServerType(String serverType) {
this.serverType=serverType;
return this;
}
public Builder setListenerType(String listenerType) {
this.listenerType=listenerType;
return this;
}
}
#Override
public String toString() {
return "BootServer [port=" + port + ", serverName=" + serverName + ", serverType=" + serverType
+ ", listenerType=" + listenerType + "]";
}
}

Access to class attributes' values using Java Annotations

I am working with a java example using annotations, I created a simple POJO (java bean) using annotations to its attributes. I want to have the ability to create new objects of this type and retrieve the values of its attributes using the annotations created.
My POJO :
import java.io.Serializable;
import annotations.BusinessObject;
import annotations.BusinessObjectAttribute;
import annotations.BusinessObjectName;
import annotations.BusinessObjectPolicy;
import annotations.BusinessObjectRevision;
import annotations.BusinessObjectVault;
#BusinessObject
public class IndusTask implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
// Mandatory to create new object !
#BusinessObjectName
private String taskName;
#BusinessObjectRevision
private String taskRevision;
#BusinessObjectVault
private String vault;
// Mandatory to invoke iTask.create(context, policy) in Database
#BusinessObjectPolicy
private String policy;
//Specific attributes
#BusinessObjectAttribute
private String taskDescription;
#BusinessObjectAttribute
private String creationDate;
#BusinessObjectAttribute
private Integer weight;
public IndusTask() {
}
public IndusTask(String taskName, String taskRevision, String vault, String policy, String taskDescription,
String creationDate, Integer weight) {
super();
this.taskName = taskName;
this.taskRevision = taskRevision;
this.vault = vault;
this.policy = policy;
this.taskDescription = taskDescription;
this.creationDate = creationDate;
this.weight = weight;
}
public String getTaskName() {
return taskName;
}
public void setTaskName(String taskName) {
this.taskName = taskName;
}
public String getTaskRevision() {
return taskRevision;
}
public void setTaskRevision(String taskRevision) {
this.taskRevision = taskRevision;
}
public String getVault() {
return vault;
}
public void setVault(String vault) {
this.vault = vault;
}
public String getTaskDescription() {
return taskDescription;
}
public void setTaskDescription(String taskDescription) {
this.taskDescription = taskDescription;
}
public String getCreationDate() {
return this.creationDate;
}
public void setCreationDate(String creationDate) {
this.creationDate = creationDate;
}
public Integer getWeight() {
return weight;
}
public void setWeight(Integer weight) {
this.weight = weight;
}
public String getPolicy() {
return policy;
}
public void setPolicy(String policy) {
this.policy = policy;
}
}
Example of attributes' declaration:
*Business Object Type declaration
package annotations;
import java.lang.annotation.*;
//#Target(ElementType.TYPE)
#Retention(RetentionPolicy.RUNTIME)
public #interface BusinessObject {
}
*Business Object Name Attribute:
package annotations;
import java.lang.annotation.*;
//#Target(ElementType.FIELD)
#Retention(RetentionPolicy.RUNTIME)
public #interface BusinessObjectName {
}
I Created a main to test if all the annotations are detected:
public class MainImpl {
public static void main(String[] args) {
// TODO Auto-generated method stub
IndusTask myTask = new IndusTask("mytstTask", "001", "eService Production", "TstTask Process",
"myTstTask Description", "2018/02/16#15:30:10:GMT", 200);
System.out.println(myTask.getClass().getAnnotations().length);
}
}
Output is displaying 1 ! so only the first annotation is detected !
I was told also that the object attributes values can be accessed using these annotation (something similar to) :
object.getClass().getAnnotations()
How can i do ?
You need to iterate through the fields, get their annotations and set the value wherever the annotation matches (it can match multiple fields):
#Retention(RetentionPolicy.RUNTIME)
public #interface Field1 {}
#Retention(RetentionPolicy.RUNTIME)
public #interface Field2 {}
public static class UnderTest {
#Field1
private String field1;
#Field2
private int field2;
public UnderTest(String field1, int field2) {
this.field1 = field1;
this.field2 = field2;
}
#Override
public String toString() {
return field1 + "=" + field2;
}
}
public static void setter(Object obj, Class<? extends Annotation> fieldAnnotation, Object fieldValue) throws IllegalAccessException {
for (Field field: obj.getClass().getDeclaredFields()) {
for (Annotation annot: field.getDeclaredAnnotations()) {
if (annot.annotationType().isAssignableFrom(fieldAnnotation)) {
if (!field.isAccessible()) {
field.setAccessible(true);
}
field.set(obj, fieldValue);
}
}
}
}
public static void main(String[] argv) throws IllegalAccessException {
UnderTest underTest = new UnderTest("A", 1);
System.out.println(underTest);
setter(underTest, Field1.class, "B");
setter(underTest, Field2.class, 2);
System.out.println(underTest);
}
Running this prints
A=1
B=2
Sounds like you're after the annotations on the fields too?
E.g. for the first private field:
myTask.getClass().getDeclaredFields()[0].getAnnotations()
Note depending how you're accessing a private field, you will sometimes also need to first ensure it is accessible:
...getDeclaredFields()[0].setAccessible(true);
[edit]
The values are reachable too from the fields. A basic worked example:
for (Field f : myTask.getClass().getDeclaredFields()) {
f.setAccessible(true);
System.out.println(f.getName() + "=" + f.get(myTask));
System.out.println(" annotations=" + java.util.Arrays.toString(f.getAnnotations()));
}

Enum with a getter

Is an enum able to store references to a getter method, using a Supplier?
To be use like that :
String value = myEnum.getValue(object)
I can't figure how to write it without compiling errors.
If I get you right then you want to do something like this:
import java.util.function.DoubleSupplier;
public class Test {
enum MathConstants {
PI(Test::getPi), E(Test::getE);
private final DoubleSupplier supply;
private MathConstants(DoubleSupplier supply) {
this.supply = supply;
}
public double getValue() {
return supply.getAsDouble();
}
}
public static void main(String... args) {
System.out.println(MathConstants.PI.getValue());
}
public static double getPi() {
return Math.PI;
}
public static double getE() {
return Math.E;
}
}
It's not very difficult if the return type for all the getters is the same. Consider the following PoJo class:
public static class MyPoJo {
final String foo, bar;
public MyPoJo(String foo, String bar) {
this.foo = foo;
this.bar = bar;
}
public String getFoo() {
return foo;
}
public String getBar() {
return bar;
}
public int getBaz() {
return 5;
}
}
Then we may have such enum:
public static enum Getters {
FOO(MyPoJo::getFoo), BAR(MyPoJo::getBar);
private final Function<MyPoJo, String> fn;
private Getters(Function<MyPoJo, String> fn) {
this.fn = fn;
}
public String getValue(MyPoJo object) {
return fn.apply(object);
}
}
And use it like this:
System.out.println(Getters.FOO.getValue(new MyPoJo("fooValue", "barValue"))); // fooValue
However it would be problematic if you want to return different types. In this case I'd suggest to use normal class with predefined instances instead of enum:
public static final class Getters<T> {
public static final Getters<String> FOO = new Getters<>(MyPoJo::getFoo);
public static final Getters<String> BAR = new Getters<>(MyPoJo::getBar);
public static final Getters<Integer> BAZ = new Getters<>(MyPoJo::getBaz);
private final Function<MyPoJo, T> fn;
private Getters(Function<MyPoJo, T> fn) {
this.fn = fn;
}
public T getValue(MyPoJo object) {
return fn.apply(object);
}
}
Usage is the same:
System.out.println(Getters.FOO.getValue(new MyPoJo("fooValue", "barValue"))); // fooValue
System.out.println(Getters.BAZ.getValue(new MyPoJo("fooValue", "barValue"))); // 5

Categories