I am a fresher and I need to know how to write JUnit test cases for this class. Can anyone help me out?
package com.jpmc.cb.creos.util.grid;
public class GridHelper {
public static List<GridFilter> getGridFilters(String jsonFilters)throws JsonParseException, JsonMappingException, IOException
{
List<GridFilter> filters = new ArrayList<GridFilter>();
GridFilter filter[] = new ObjectMapper().readValue(jsonFilters,
GridFilter[].class);
for (int i = 0; i < filter.length; i++) {
filters.add(filter[i]);
}
return filters;
}
}
This is the GridFilter Class:
package com.jpmc.cb.creos.util.grid;
public class GridFilter {
private String property;
private String value;
private String operator;
public GridFilter() {}
public GridFilter(String property, String operator, String value)
{
this.property = property;
this.value = value;
this.operator = operator;
}
public String getProperty() {
return property;
}
public void setProperty(String property) {
this.property = property;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getOperator() {
return operator;
}
public void setOperator(String operator) {
this.operator = operator;
}
}
Here are some ideas for what to test. Write test methods for (at least) the following cases:
a well formed json with 2 filters should return a list with two filters with matching values
a well formed json with no filters should return an empty list
a malformed json should raise a JsonParseException
other bad data to raise the other exception types
How to write the test cases? Not clear what you're asking. But here's an example:
#Test
public void empty_json_gives_empty_list() throws Exception {
assertEquals(Collections.emptyList(), GridHelper.getGridFilters("[]"));
}
Related
I am using Flink 1.12.0, and I have following simple test case:
I defined two model class(AbstractDataModel is super type, while the ConcreteModel is the sub type):
public interface AbstractDataModel {
public String getValue();
}
public class ConcreteModel implements AbstractDataModel {
private String key;
private String value;
public ConcreteModel() {
}
public ConcreteModel(String key, String value) {
this.key = key;
this.value = value;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
Then, I define a simple application as follows,which is to map the ConcreteModel to string,
The MapFunction is using the super type AbstractDataModel, but there is compiling error complaining:
Required type:
MapFunction<com.ConcreteModel,java.lang.String>
Provided:
MyMapFunction
I would ask how to fix this problem if I still want to use AbstractDataModel as the generic type in the MapFunction
import org.apache.flink.api.common.functions.MapFunction;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
class MyMapFunction implements MapFunction<AbstractDataModel, String> {
public String map(AbstractDataModel model) throws Exception {
return model.getValue();
}
}
public class ConcreteModelTest {
public static void main(String[] args) {
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
// env.registerType(ConcreteModel.class);
// env.registerType(AbstractDataModel.class);
//
DataStream<String> ds = env.fromElements(new ConcreteModel("a", "1"), new ConcreteModel("b", "2")).map(new MyMapFunction());
ds.print();
env.execute();
}
}
That happens basically because Flink cannot process POJO objects due to its distributed environment. Here is what says the docs:
15:45:51,460 INFO org.apache.flink.api.java.typeutils.TypeExtractor -
Class … cannot be used as a POJO type because not all fields are valid
POJO fields, and must be processed as GenericType. Please read the
Flink documentation on “Data Types & Serialization” for details of the
effect on performance.
You can use the ResultTypeQueryable and define the return type with TypeInformation.of(AbstractDataModel.class) on the method public TypeInformation getProducedType().
This interface can be implemented by functions and input formats to
tell the framework about their produced data type. This method acts as
an alternative to the reflection analysis that is otherwise performed
and is useful in situations where the produced data type may vary
depending on parametrization.
import org.apache.flink.api.common.functions.MapFunction;
import org.apache.flink.api.common.typeinfo.TypeInformation;
import org.apache.flink.api.java.typeutils.ResultTypeQueryable;
public class MyMapFunction implements MapFunction<AbstractDataModel, String>,
ResultTypeQueryable {
#Override
public String map(AbstractDataModel value) throws Exception {
return value.getValue();
}
#Override
public TypeInformation getProducedType() {
return TypeInformation.of(AbstractDataModel.class);
}
}
public class ConcreteModelTest {
public static void main(String[] args) throws Exception {
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
AbstractDataModel concreteModel01 = new ConcreteModel("a", "1");
AbstractDataModel concreteModel02 = new ConcreteModel("a", "2");
DataStream<String> ds = env
.fromElements(concreteModel01, concreteModel02)
.map(new MyMapFunction());
ds.print();
env.execute();
}
}
or an easy way is to just call map with TypeInformation.of(String.class). Then you don't need to implement ResultTypeQueryable at MyMapFunction.
DataStream<String> ds = env
.fromElements(concreteModel01, concreteModel02)
.map(new MyMapFunction(), TypeInformation.of(String.class));
and then just use your interface with its class implementation.
public interface AbstractDataModel {
public String getValue();
}
public class ConcreteModel implements AbstractDataModel {
private String key;
private String value;
public ConcreteModel() {
}
public ConcreteModel(String key, String value) {
this.key = key;
this.value = value;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
I have defined an enum in a class A
public class A{
public static final String CANDY = "yelow candy";
public static final String CAKE = "cookie";
public enum Yummy{
CANDY, CAKE;
}
}
In another package,
public class C {
Yummy[] yummies = A.Yummy.values();
for (Yummy yum : yummies){
String yumString = yum.toString();
System.out.println("yum =" + yumString);
}
}
I get CANDY and CAKE as a result, not "yelow candy" and "cookie".
What does I need to change to get the "yelow candy" and "cookie ?
You've defined an enum "A.Yummy" and also two strings, "A.Candy" and "A.CAKE".
They aren't linked at all.
You will want to delete the strings and add something like https://stackoverflow.com/a/13291109/1041364
public enum Yummy {
CANDY("yelow candy"),
CAKE("cookie");
private String description;
private Yummy(String description) {
this.description= description;
}
public String toString() {
return this.description;
}
}
Try the following:
public enum Yummy{
CANDY ("yellow candy"), CAKE ("cookie");
private String name;
private Yummy(String name) {
this.name = name;
}
public String toString() {
return this.name;
}
}
Additional values for enums should be hold in properties. You have to provide constructor to set up those properties.
public enum Yummy {
CANDY("yelow candy"), CAKE("cookie");
private String value;
private Yummy(String value) {
this.value = value;
}
};
And then in code you can use CANDY.value or override toString() method.
Try this:
class Ideone
{
public static void main (String[] args) throws java.lang.Exception
{
for (Yummy yum : Yummy.values()) {
System.out.printf("%s, %s\n", yum, yum.getValue());
}
}
}
enum Yummy {
CANDY("yelow candy"),
CAKE("cookie");
private String value;
private Yummy(String value) {
this.value = value;
}
public String getValue() {
return this.value;
}
}
I have no idea what to do with this problem.
I have a JSON object to assist in value input through POST (using Play Framework) that structures like this:
{
"start_absolute": 1403185486254,
"end_absolute": 1403185486254,
"metrics": [
{
"name": "parts",
"tags": [
{
"key":"machine",
"value":"10"
}
],
"sampling":
{
"value": 1,
"unit": "minutes"
}
}
]
}
And in server side i try to process the info like this:
Form<QueryForm> queryForm = Form.form(QueryForm.class).bindFromRequest();
if (queryForm.hasErrors()) {
return badRequest(queryForm.errorsAsJson());
}
QueryForm queryInfo = queryForm.get();
the classes used to define the JSON object in java
public class QueryForm {
private Date start_absolute;
private Date end_absolute;
private List<MetricForm> metrics= Lists.newArrayList();
public Date getStart_absolute() {
return start_absolute;
}
public void setStart_absolute(long start_absolute) {
this.start_absolute = new Date(start_absolute);
}
public Date getEnd_absolute() {
return end_absolute;
}
public void setEnd_absolute(long end_absolute) {
this.end_absolute =new Date(end_absolute);
}
public List<MetricForm> getMetrics() {
return metrics;
}
public void setMetrics(List<MetricForm> metrics) {
this.metrics = metrics;
}
#Override
public String toString() {
return "QueryForm[start_absolute="+start_absolute+", end_absolute="+end_absolute+", metrics="+metrics+"]";
}
.
public class MetricForm {
private String name;
private List<Tag> tags= Lists.newArrayList();
private RelativeTimeForm sampling= new RelativeTimeForm(1,"milliseconds");
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Tag> getTags() {
return tags;
}
public void setTags(List<Tag> tags) {
this.tags.addAll(tags);
}
public RelativeTimeForm getSampling() {
return sampling;
}
public void setSampling(int val, String unit) {
this.sampling.setUnit(unit);
this.sampling.setVal(val);
}
#Override
public String toString() {
return "MetricForm[name="+name+", tags="+tags+",sampling="+sampling+"]";
}
.
public class Tag {
private String key;
private String value;
public Tag(String key, String value) {
this.key = key;
this.value = value;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
#Override
public String toString() {
return String.format(
"Tag[key=%s, value='%s']",
key, value
);
}
}
.
public class RelativeTimeForm {
private int value;
private String unit;
public RelativeTimeForm (int val, String unit){
this.setValue(val);
this.setUnit(unit);
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public String getUnit() {
return unit;
}
public void setUnit(String unit) {
this.unit = unit;
}
#Override
public String toString() {
return "RelativeTimeForm[value="+value+", unit="+unit+"]";
}
I'm not experienced working with play.data.Form but in previous ocasions with simpler objects (Using primitive data types and String) this worked fine but when i tried to POST to the play application (Header: Content-Type = application/json; charset=utf-8) it occurs an Internal Server Error:
play.api.Application$$anon$1: Execution exception [[InvalidPropertyException:
Invalid property 'metrics[0].tags[0]' of bean class [model.QueryForm]: Illegal
attempt to get property 'tags' threw exception; nested exception is
org.springframework.beans.NullValueInNestedPathException: Invalid property
'metrics[0].tags' of bean class [model.QueryForm]: Could not instatiate property
path:
java.lang:InstatiationException: [model.Tag]
Any one can help with this? I can´t figure out what to do. Is it to complex of an object to convert from JSON? Do i need to add some JSON Annotations (not currently using them)?
I have no clue how to fix this
UPDATE: I narrowed it down to the Tag class. for some reason i'm not able to instatiate Tag through JSON. I even tried setting a single Tag instance in the same level as the dates and it gives the same error (It work for Sampling)
RESOLVED:
Spring binding exception when a form is submitted
The answer is in the post above. I have to set an empty construtor in Tag class for it to work.
public Tag(){
}
The exception means, that one or more attributes aren't instantiated.
private List<MetricForm> metrics = new ...;
private List<Tag> tags = new ...;
private RelativeTimeForm sampling = new ...;
should do it.
In the case you get problems to read in your time values: Instead of using Date type directly to read in, I would use long to read in the time values and then (internally) convert them to Date objects.
For some reason pulling a cached object back from the cache in Robospice is always null. Is there something I'm doing wrong?
getSpiceManager().execute(cardRequest, Card.class.getName(),
DurationInMillis.ONE_DAY, new CardRequestListener());
Is how it's executed. The spice manager is created as follows:
mSpiceManager = new SpiceManager(JacksonGoogleHttpClientSpiceService.class);
And the card class is as follows:
#JsonInclude(JsonInclude.Include.NON_NULL)
#JsonPropertyOrder({
"iosThumbHighRes",
"iosThumb",
"iosLargeHiRes",
"iosLargeHighRes",
"iosLarge"
})
public class Card {
#JsonProperty("iosThumbHighRes")
private String iosThumbHighRes;
#JsonProperty("iosThumb")
private String iosThumb;
#JsonProperty("iosLargeHiRes")
private String iosLargeHiRes;
#JsonProperty("iosLargeHighRes")
private String iosLargeHighRes;
#JsonProperty("iosLarge")
private String iosLarge;
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
#JsonProperty("iosThumbHighRes")
public String getIosThumbHighRes() {
return iosThumbHighRes;
}
#JsonProperty("iosThumbHighRes")
public void setIosThumbHighRes(String iosThumbHighRes) {
this.iosThumbHighRes = iosThumbHighRes;
}
#JsonProperty("iosThumb")
public String getIosThumb() {
return iosThumb;
}
#JsonProperty("iosThumb")
public void setIosThumb(String iosThumb) {
this.iosThumb = iosThumb;
}
#JsonProperty("iosLargeHiRes")
public String getIosLargeHiRes() {
return iosLargeHiRes;
}
#JsonProperty("iosLargeHiRes")
public void setIosLargeHiRes(String iosLargeHiRes) {
this.iosLargeHiRes = iosLargeHiRes;
}
#JsonProperty("iosLargeHighRes")
public String getIosLargeHighRes() {
return iosLargeHighRes;
}
#JsonProperty("iosLargeHighRes")
public void setIosLargeHighRes(String iosLargeHighRes) {
this.iosLargeHighRes = iosLargeHighRes;
}
#JsonProperty("iosLarge")
public String getIosLarge() {
return iosLarge;
}
#JsonProperty("iosLarge")
public void setIosLarge(String iosLarge) {
this.iosLarge = iosLarge;
}
#Override
public String toString() {
return ToStringBuilder.reflectionToString(this);
}
#Override
public int hashCode() {
return HashCodeBuilder.reflectionHashCode(this);
}
#Override
public boolean equals(Object other) {
return EqualsBuilder.reflectionEquals(this, other);
}
#JsonAnyGetter
public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}
#JsonAnySetter
public void setAdditionalProperties(String name, Object value) {
this.additionalProperties.put(name, value);
}
}
Is there something else I need to set?
Thanks, Graeme
The Google Http Client uses the #Key annotation. You are using Jackson annotation which is not supported by Googe Http Java Client, as it provides an abstraction layer over all serialisation solutions (gson/jackson).
I've a generic field in User.java. I want to use the value of T in json.
public class User<T> {
public enum Gender {MALE, FEMALE};
private T field;
private Gender _gender;
private boolean _isVerified;
private byte[] _userImage;
public T getField() { return field; }
public boolean isVerified() { return _isVerified; }
public Gender getGender() { return _gender; }
public byte[] getUserImage() { return _userImage; }
public void setField(T f) { field = f; }
public void setVerified(boolean b) { _isVerified = b; }
public void setGender(Gender g) { _gender = g; }
public void setUserImage(byte[] b) { _userImage = b; }
}
and mapper class is:
public class App
{
public static void main( String[] args ) throws JsonParseException, JsonMappingException, IOException
{
ObjectMapper mapper = new ObjectMapper();
Name n = new Name();
n.setFirst("Harry");
n.setLast("Potter");
User<Name> user = new User<Name>();
user.setField(n);
user.setGender(Gender.MALE);
user.setVerified(false);
mapper.writeValue(new File("user1.json"), user);
}
}
and the json output is :
{"field":{"first":"Harry","last":"Potter"},"gender":"MALE","verified":false,"userImage":null}
In the output, i want Name to be appeared in place of field. How do i do that. Any help?
I think what u ask is not JSON's default behavior. Field name is the "key" of the json map, not the variable name. U should rename the field or make some String process to do it.
private T field;
change the above to this:
private T name;
You need a custom serializer to do that. That's a runtime data transformation and Jackson has no support for data transformation other than with a custom serializer (well, there's wrapping/unwrapping of value, but let's not go there). Also, you will need to know in advance every type of transformation you want to apply inside your serializer. The following works:
public class UserSerializer extends JsonSerializer<User<?>> {
private static final String USER_IMAGE_FIELD = "userImage";
private static final String VERIFIED_FIELD = "verified";
private static final String FIELD_FIELD = "field";
private static final String NAME_FIELD = "name";
#Override
public void serialize(User<?> value, JsonGenerator jgen, SerializerProvider provider) throws IOException,
JsonProcessingException {
jgen.writeStartObject();
if (value.field instanceof Name) {
jgen.writeFieldName(NAME_FIELD);
} else {
jgen.writeFieldName(FIELD_FIELD);
}
jgen.writeObject(value.field);
jgen.writeStringField("gender", value._gender.name());
jgen.writeBooleanField(VERIFIED_FIELD, value._isVerified);
if (value._userImage == null) {
jgen.writeNullField(USER_IMAGE_FIELD);
} else {
jgen.writeBinaryField(USER_IMAGE_FIELD, value._userImage);
}
jgen.writeEndObject();
}
}