PowerMock ExpectNew creating real objects instead of mocked Ones - powermock

public class PersistenceManager {
public boolean addUser(User user) {
UserPersistor userPersistor = new UserPersistor(user) {
#Override
void somemethod() {
// TODO Auto-generated method stub
}
};
userPersistor.addUser();
System.out.println("PersistenceManager added user ");
return true;
}
class User {
public String firstName;
public String lastName;
public User(String firstName, String lastName) {
super();
this.firstName = firstName;
this.lastName = lastName;
}
}
abstract class UserPersistor {
public UserPersistor( ) {
}
public UserPersistor(User user) {
}
public void addUser() {
System.err.println("UserPersistor added user ");
}
abstract void somemethod();
}
}
import static org.powermock.api.easymock.PowerMock.createMock;
import static org.powermock.api.easymock.PowerMock.expectNew;
import static org.powermock.api.easymock.PowerMock.expectLastCall;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest( PersistenceManager.class )
public class PersistenceManagerTest {
private User user = null;
#Before
public void before() throws Exception {
user = createMock(User.class);
UserPersistor userPersistor = createMock(UserPersistor.class);
userPersistor.addUser();
expectLastCall();
expectNew(UserPersistor.class, user).andReturn(userPersistor);
PowerMock.replayAll();
}
#Test
public void testaddUser() {
PersistenceManager tested = new PersistenceManager();
tested.addUser(user);
PowerMock.verifyAll();
}
}
Whats wrong with above code? I dont see mocked object for UserPersistor. Meaning, i dont want to see "UserPersistor added user " printed. It should not do anything. But it is printing it since real object of UserPersistor is created. I am facing this problem in my actual project, thought would simulate and try to solve in a much smaller context. But I am stumped.

That's because you are not expecting to instantiate UserPersistor but an anonymous inner class extending UserPersistor.
To do that you need to retrieve that class, mock it and expect it. PowerMock has a Whitebox class to do that. You are exposing the class implementation when using it. I would recommend that you refactor your code to inject the code instead. But if you really want to, you should write this:
#Before
public void before() throws Exception {
user = createMock(PersistenceManager.User.class);
Class<Object> clazz = Whitebox.getAnonymousInnerClassType(PersistenceManager.class, 1);
PersistenceManager.UserPersistor userPersistor = createMock(clazz);
userPersistor.addUser();
expectNew(clazz, user).andReturn(userPersistor);
PowerMock.replayAll();
}

Related

Serializing and Deserializing Lambda with Jackson

I am trying to serialise and deserialise a class RuleMessage but can't get it to work. Here is my code:
public class RuleMessage {
private String id;
private SerializableRunnable sRunnable;
public RuleMessage(String id, SerializableRunnable sRunnable) {
this.id = id;
this.sRunnable = sRunnable;
}
}
public interface SerializableRunnable extends Runnable, Serializable {
}
#Test
public void testSerialization() throws JsonProcessingException {
MAPPER.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL,
JsonTypeInfo.As.PROPERTY);
SerializableRunnable r = () -> System.out.println("Serializable!");
RuleMessage rule = new RuleMessage("1", r);
System.out.println(MAPPER.writeValueAsString(businessRule));
}
I am using Java 8. Can someone tell me if this is possible in the Jackson library?
Jackson was created to keep object state not behaviour. This is why it tries to serialise POJO's properties using getters, setters, etc. Serialising lambdas break this idea. Theres is no any property to serialise, only a method which should be invoked. Serialising raw lambda object is really bad idea and you should redesign your app to avoid uses cases like this.
In your case SerializableRunnable interface extends java.io.Serializable which gives one option - Java Serialisation. Using java.io.ObjectOutputStream we can serialise lambda object to byte array and serialise it in JSON payload using Base64 encoding. Jackson supports this scenario providing writeBinary and getBinaryValue methods.
Simple example could look like below:
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class JsonLambdaApp {
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
SerializableRunnable action = () -> System.out.println("Serializable!");
String json = mapper.writeValueAsString(new RuleMessage("1", action));
System.out.println(json);
RuleMessage ruleMessage = mapper.readValue(json, RuleMessage.class);
ruleMessage.getsRunnable().run();
}
}
#JsonSerialize(using = LambdaJsonSerializer.class)
#JsonDeserialize(using = LambdaJsonDeserializer.class)
interface SerializableRunnable extends Runnable, Serializable {
}
class LambdaJsonSerializer extends JsonSerializer<SerializableRunnable> {
#Override
public void serialize(SerializableRunnable value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
ObjectOutputStream outputStream = new ObjectOutputStream(byteArrayOutputStream)) {
outputStream.writeObject(value);
gen.writeBinary(byteArrayOutputStream.toByteArray());
}
}
}
class LambdaJsonDeserializer extends JsonDeserializer<SerializableRunnable> {
#Override
public SerializableRunnable deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
byte[] value = p.getBinaryValue();
try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(value);
ObjectInputStream inputStream = new ObjectInputStream(byteArrayInputStream)) {
return (SerializableRunnable) inputStream.readObject();
} catch (ClassNotFoundException e) {
throw new IOException(e);
}
}
}
class RuleMessage {
private String id;
private SerializableRunnable sRunnable;
#JsonCreator
public RuleMessage(#JsonProperty("id") String id, #JsonProperty("sRunnable") SerializableRunnable sRunnable) {
this.id = id;
this.sRunnable = sRunnable;
}
public String getId() {
return id;
}
public SerializableRunnable getsRunnable() {
return sRunnable;
}
}
Above code prints JSON:
{
"id" : "1",
"sRunnable" : "rO0ABXNyACFqYXZhLmxhbmcuaW52b2tlLlNlcmlhbGl6ZWRMYW1iZGFvYdCULCk2hQIACkkADmltcGxNZXRob2RLaW5kWwAMY2FwdHVyZWRBcmdzdAATW0xqYXZhL2xhbmcvT2JqZWN0O0wADmNhcHR1cmluZ0NsYXNzdAARTGphdmEvbGFuZy9DbGFzcztMABhmdW5jdGlvbmFsSW50ZXJmYWNlQ2xhc3N0ABJMamF2YS9sYW5nL1N0cmluZztMAB1mdW5jdGlvbmFsSW50ZXJmYWNlTWV0aG9kTmFtZXEAfgADTAAiZnVuY3Rpb25hbEludGVyZmFjZU1ldGhvZFNpZ25hdHVyZXEAfgADTAAJaW1wbENsYXNzcQB+AANMAA5pbXBsTWV0aG9kTmFtZXEAfgADTAATaW1wbE1ldGhvZFNpZ25hdHVyZXEAfgADTAAWaW5zdGFudGlhdGVkTWV0aG9kVHlwZXEAfgADeHAAAAAGdXIAE1tMamF2YS5sYW5nLk9iamVjdDuQzlifEHMpbAIAAHhwAAAAAHZyABxjb20uY2Vsb3hpdHkuSnNvblR5cGVJbmZvQXBwAAAAAAAAAAAAAAB4cHQAIWNvbS9jZWxveGl0eS9TZXJpYWxpemFibGVSdW5uYWJsZXQAA3J1bnQAAygpVnQAHGNvbS9jZWxveGl0eS9Kc29uVHlwZUluZm9BcHB0ABZsYW1iZGEkbWFpbiQ1YzRiNmEwOCQxcQB+AAtxAH4ACw=="
}
and lambda:
Serializable!
See also:
How to serialize a lambda?
How to serialize a lambda function in Java?
First, in RuleMessage you have to either create getters / setters or make the fields public in order to provide Jackson access to the fields.
Your code then prints something like this:
{"#class":"RuleMessage","id":"1","sRunnable":{"#class":"RuleMessage$$Lambda$20/0x0000000800b91c40"}}
This JSON document cannot be deserialized because RuleMessage has no default constructor and the lambda cannot be constructed.
Instead of the lambda, you could create a class:
public class Runner implements SerializableRunnable {
#Override
public void run() {
System.out.println("Serializable!");
}
}
and construct your pojo like this:
new RuleMessage("1", new Runner())
The Jackson deserializer is now able to reconstruct the objects and execute the runner.

Unable to get rid of 'Exception while fetching data(/{apiName})' in graphql-spqr-spring-boot-starter

I’m using ‘graphql-spqr-spring-boot-starter’ library version 0.0.4 of ‘io.leangen.graphql’. I'm able to customize errors. See the below code and screenshot for reference:
Models:
#Getter
#Setter
#ToString
#Entity
#Accessors
public class Student {
#Id
#GraphQLQuery(name = "id", description = "A Student's ID")
private Long id;
#GraphQLQuery(name = "name", description = "A student's name")
private String name;
private String addr;
}
Service class:
#Service
#GraphQLApi
public class StudentService{
private final StudentRepository studentRepository;
private final AddressRepository addressRepository;
public StudentService(StudentRepository studentRepository, AddressRepository addressRepository) {
this.addressRepository = addressRepository;
this.studentRepository = studentRepository;
}
#GraphQLQuery(name = "allStudents")
public List<Student> getAllStudents() {
return studentRepository.findAll();
}
#GraphQLQuery(name = "student")
public Optional<Student> getStudentById(#GraphQLArgument(name = "id") Long id) {
if(studentRepository.findById(id) != null)
return studentRepository.findById(id);
throw new StudentNotFoundException("We were unable to find a student with the provided id", "id");
}
#GraphQLMutation(name = "saveStudent")
public Student saveStudent(#GraphQLArgument(name = "student") Student student) {
if(student.getId() == null)
throw new NoIdException("Please provide an Id to create a Student entry.");
return studentRepository.save(student);
}
}
Customized Exception class:
import java.util.List;
import graphql.ErrorType;
import graphql.GraphQLError;
import graphql.language.SourceLocation;
public class NoIdException extends RuntimeException implements GraphQLError {
private String noIdMsg;
public NoIdException(String noIdMsg) {
this.noIdMsg = noIdMsg;
}
#Override
public List<SourceLocation> getLocations() {
// TODO Auto-generated method stub
return null;
}
#Override
public ErrorType getErrorType() {
// TODO Auto-generated method stub
return ErrorType.ValidationError;
}
#Override
public String getMessage() {
// TODO Auto-generated method stub
return noIdMsg;
}
}
However, I’m not sure how to get rid of Exception while fetching data (/saveStudent) as seen on the above screenshot for the message field. I know we can have GraphQLExceptionHandler class which implements GraphQLErrorHandler (graphql-java-kickstart). But what is the option for sqpr-spring-boot-starter?
import graphql.*;
import graphql.kickstart.execution.error.*;
import org.springframework.stereotype.*;
import java.util.*;
import java.util.stream.*;
#Component
public class GraphQLExceptionHandler implements GraphQLErrorHandler {
#Override
public List<GraphQLError> processErrors(List<GraphQLError> list) {
return list.stream().map(this::getNested).collect(Collectors.toList());
}
private GraphQLError getNested(GraphQLError error) {
if (error instanceof ExceptionWhileDataFetching) {
ExceptionWhileDataFetching exceptionError = (ExceptionWhileDataFetching) error;
if (exceptionError.getException() instanceof GraphQLError) {
return (GraphQLError) exceptionError.getException();
}
}
return error;
}
}
Could someone please help me how can I remove this statement and send just the specific message?
You can create a Bean and override DataFetcherExceptionHandler. To override it, you have to override the execution strategy too:
#Bean
public GraphQL graphQL(GraphQLSchema schema) {
return GraphQL.newGraphQL(schema)
.queryExecutionStrategy(new AsyncExecutionStrategy(new CustomDataFetcherExceptionHandler()))
.mutationExecutionStrategy(new AsyncSerialExecutionStrategy(new CustomDataFetcherExceptionHandler()))
.build();
}
private static class CustomDataFetcherExceptionHandler implements DataFetcherExceptionHandler {
#Override
public DataFetcherExceptionHandlerResult onException(DataFetcherExceptionHandlerParameters handlerParameters) {
Throwable exception = handlerParameters.getException();
SourceLocation sourceLocation = handlerParameters.getSourceLocation();
CustomExceptionWhileDataFetching error = new CustomExceptionWhileDataFetching(exception, sourceLocation);
return DataFetcherExceptionHandlerResult.newResult().error(error).build();
}
}
private static class CustomExceptionWhileDataFetching implements GraphQLError {
private final String message;
private final List<SourceLocation> locations;
public CustomExceptionWhileDataFetching(Throwable exception, SourceLocation sourceLocation) {
this.locations = Collections.singletonList(sourceLocation);
this.message = exception.getMessage();
}
#Override
public String getMessage() {
return this.message;
}
#Override
public List<SourceLocation> getLocations() {
return this.locations;
}
#Override
public ErrorClassification getErrorType() {
return ErrorType.DataFetchingException;
}
}

How to set the private member variable of a class in test method with powermock

I am writing a junit test for the below constructor. i tried to set the value of mapRecords variable using Membermodifier but still i get the zero as the size of list. being a newbie in junit i am not getting the exact idea to do it. if someone can help it would be appreciated.
public class Transform {
private MapMetadataDAO mapMetadataDAO;
private Map<String,String> srcTargetMap;
private List<MapMetadata> mapRecords;
public Transform(String transformationId) throws GenericFlowException {
try {
mapMetadataDAO=new MapMetadataDAO();
} catch (DAOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mapRecords = mapMetadataDAO.findMapMetadataByTransformationID(transformationId);
System.out.println(mapRecords.size());
if(mapRecords.isEmpty()){
throw new GenericFlowException("Map meta data is not defined for the transformationId "+transformationId);
}
map();
}
}
Test class :
If i don't create the object using new, i am not able to invoke the constructor
#RunWith(PowerMockRunner.class)
#PrepareForTest({Transform.class, MapMetadataDAO.class})
public class TransformTest {
#Test
public void constructorTest() throws Exception
{
PowerMockito.suppress(PowerMockito.constructor(MapMetadataDAO.class));
MapMetadataDAO dao = PowerMockito.mock(MapMetadataDAO.class);
MapMetadata mapMetaData = PowerMockito.mock(MapMetadata.class);
PowerMockito.whenNew(MapMetadataDAO.class).withNoArguments().thenReturn(dao);
List<MapMetadata> list = new ArrayList<>();
list.add(mapMetaData);
Transform trans = PowerMockito.mock(Transform.class, Mockito.CALLS_REAL_METHODS);
MemberModifier.field(Transform.class, "mapRecords").set(trans, list);
PowerMockito.when(dao.findMapMetadataByTransformationID("transformationID")).thenReturn(list);
Transform transform = new Transform("transformationId");
PowerMockito.whenNew(Transform.class).withAnyArguments().thenReturn(trans);
}
}
With some changes in your class I made it work
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
#RunWith(org.powermock.modules.junit4.PowerMockRunner.class)
#PrepareForTest({MapMetadataDAO.class, Transform.class})
public class TransformTest {
#Mock
private MapMetadataDAO mapMetadataDAO;
#Mock
private Map<String,String> srcTargetMap;
#InjectMocks
private Transform Transform = new Transform();
#Before
public void init() {
MockitoAnnotations.initMocks(this);
}
#Test
public void testConstructor() throws Exception {
List<MapMetadata> mapRecords = new ArrayList<MapMetadata>();
mapRecords.add(new MapMetadata());
PowerMockito.whenNew(MapMetadataDAO.class).withNoArguments().thenReturn(mapMetadataDAO);
PowerMockito.when(mapMetadataDAO.findMapMetadataByTransformationID(Mockito.anyString())).thenReturn(mapRecords);
Transform.getTransform("transformationId");
}
}
class Transform{
private MapMetadataDAO mapMetadataDAO;
private Map<String,String> srcTargetMap;
private List<MapMetadata> mapRecords;
public Transform() {}
public void getTransform(String transformationId){
try {
mapMetadataDAO=new MapMetadataDAO();
mapRecords = mapMetadataDAO.findMapMetadataByTransformationID(transformationId);
System.out.println(mapRecords.size());
if(mapRecords.isEmpty()){
throw new GenericFlowException("Map meta data is not defined for the transformationId "+transformationId);
}
map();
} catch (DAOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (GenericFlowException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void map() {}
}
let me know if this is what you needed
For ease of test rewrite your class like this:
public class Transform {
private MapMetadataDAO mapMetadataDAO;
private Map<String,String> srcTargetMap;
private List<MapMetadata> mapRecords;
public Transform(MapMetadataDAO mapMedatadaDAO, String transformationId) throws GenericFlowException {
mapRecords = mapMetadataDAO.findMapMetadataByTransformationID(transformationId);
System.out.println(mapRecords.size());
if(mapRecords.isEmpty()){
throw new GenericFlowException("Map meta data is not defined for the transformationId "+transformationId);
}
map();
}
}
And then your test:
#RunWith(PowerMockRunner.class)
#PrepareForTest({MapMetadataDAO.class})
public class TransformTest {
#Test
public void constructorTest() throws Exception
{
MapMetadata mapMetaData = new MapMetadata();
List<MapMetadata> list = new ArrayList<>();
list.add(mapMetaData);
MapMetadataDAO dao = PowerMockito.mock(MapMetadataDAO.class);
String transformationId = "transformationId";
PowerMockito.when(dao.findMapMetadataByTransformationID(transformationId)).thenReturn(list);
Transform transform = new Transform(dao, transformationId);
}
}

Java/JUnit - How does testPrintMessage() get called?

In the following code, how does method testPrintMessage() get called? I dont see any code explicitly calling it.
TestRunner.java
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
public class TestRunner {
public static void main(String[] args) {
Result result = JUnitCore.runClasses(TestJunit.class);
for (Failure failure : result.getFailures()) {
System.out.println(failure.toString());
}
System.out.println(result.wasSuccessful());
}
}
TestJunit.java
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class TestJunit {
String message = "Hello World";
MessageUtil messageUtil = new MessageUtil(message);
#Test
public void testPrintMessage() {
assertEquals(message,messageUtil.printMessage());
}
}
MessageUtil.java
public class MessageUtil {
private String message;
//Constructor
//#param message to be printed
public MessageUtil(String message){
this.message = message;
}
// prints the message
public String printMessage(){
System.out.println(message);
return message;
}
}
I tested this code in Eclipse and it works:
Hello World
true
When JUnitCore.runClasses(TestJunit.class) gets called, JUnit finds all public methods annotated with #Test and invokes them reflectively.

how to handle Json body in post request in jax-rs

I have a project (homework) about JAX-RS. I'm working with NetBeans, Jersey and Tomcat.
This is my "User" class for main object in the system.
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name="user")
public class User {
//#XmlElement
//public int id ;
#XmlElement
public String username;
#XmlElement
public String fullname;
#XmlElement
public String gender;
#XmlElement
public String birthDate;
public User(){
}
public User(String username,String fullname, String gender,String birthDate){
//this.id = id;
this.username = username;
this.fullname = fullname;
this.gender = gender;
this.birthDate = birthDate;
}
}
This is my "JAXBContextResolver" Class
import com.sun.jersey.api.json.JSONConfiguration;
import com.sun.jersey.api.json.JSONJAXBContext;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;
import javax.xml.bind.JAXBContext;
#Provider
public class JAXBContextResolver implements ContextResolver<JAXBContext>{
private JAXBContext context;
private Class[] types = {User.class};
public JAXBContextResolver() throws Exception {
this.context =
new JSONJAXBContext( JSONConfiguration.mapped().build(), types);
}
#Override
public JAXBContext getContext(Class<?> objectType) {
for (Class type : types) {
if (type == objectType) {
return context;
}
}
return null;
}
}
And this is my post method in the "UserService" class
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
public List<User> createNewUser(User tUser) {
List<User> list = new ArrayList<User>();
list.add(tUser);
return list;
}
When I am trying a post new user in the localhost with RESTClient (Firefox add-ons) my request body is a json input like that:
{"user":{"username":"blabla","fullname":"blabla","gender":"M","birthDate":"05.01.1978"}}
In the post method (in the UserService class) must the variable "tUser" automatically filled with the coming input ? "tUser" variable shows null elements in it in the debugging mode like that:
If I know wrong could somebody correct me please? Why this values shows null? Must not them shows "blabla" - "blabla" - "M" - "05.01.1878" ? Could you help me please?
I solved this problem; In the JAXBContextResolver class I change the method like that :
public JAXBContextResolver() throws Exception {
this.context =
new JSONJAXBContext( JSONConfiguration.mapped().rootUnwrapping(false).build(), types);
}
The difference with the first one is adding "rootUnwrapping(false)" expression.
#XmlRootElement is not working in your example. Send
{"username":"blabla","fullname":"blabla","gender":"M","birthDate":"05.01.1978"}
instead
EDIT
1)
public List<User> createNewUser(Request tUser)
and class
class Request
{
public User user;
}
2)
public List<User> createNewUser(String tUser)
and convert String to object using google-gson or jackson json processor