multiline
multiline copied to clipboard
Error interacting with meanbean for unit tests...
When I use the multiline library in conjunction with meanbean for unit testing beans, I get an error. The error goes away when I remove the @Multiline annotation:
Cannot test bean [com.sungardas.cc.vsphere.docs.VCenterConfig]. Failed to instantiate an instance of the bean.
org.meanbean.test.BeanTestException
at org.meanbean.test.BeanTester.testBean(BeanTester.java:406)
at org.meanbean.test.BeanTester.testBean(BeanTester.java:350)
at com.sungardas.cc.vsphere.docs.BeanTester.testBeans(BeanTester.java:20)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:242)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:137)
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:112)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189)
at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165)
at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85)
at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:115)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:75)
Caused by: org.meanbean.factories.ObjectCreationException: Failed to instantiate object of type [com.sungardas.cc.vsphere.docs.VCenterConfig] due to InvocationTargetException.
at org.meanbean.factories.BasicNewObjectInstanceFactory.wrapAndRethrowException(BasicNewObjectInstanceFactory.java:94)
at org.meanbean.factories.BasicNewObjectInstanceFactory.create(BasicNewObjectInstanceFactory.java:74)
at org.meanbean.test.BeanTester.testBean(BeanTester.java:400)
... 31 more
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
at org.meanbean.factories.BasicNewObjectInstanceFactory.create(BasicNewObjectInstanceFactory.java:62)
... 32 more
Caused by: com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: Expected name at line 24 column 6
at com.google.gson.Gson.fromJson(Gson.java:818)
at com.google.gson.Gson.fromJson(Gson.java:768)
at com.google.gson.Gson.fromJson(Gson.java:717)
at com.google.gson.Gson.fromJson(Gson.java:689)
at com.sungardas.cc.vsphere.docs.VCenterConfig.<init>(VCenterConfig.java:70)
... 37 more
Caused by: com.google.gson.stream.MalformedJsonException: Expected name at line 24 column 6
at com.google.gson.stream.JsonReader.syntaxError(JsonReader.java:1505)
at com.google.gson.stream.JsonReader.doPeek(JsonReader.java:494)
at com.google.gson.stream.JsonReader.hasNext(JsonReader.java:403)
at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.read(MapTypeAdapterFactory.java:184)
at com.google.gson.internal.bind.MapTypeAdapterFactory$Adapter.read(MapTypeAdapterFactory.java:145)
at com.google.gson.Gson.fromJson(Gson.java:803)
... 41 more
The exception being caused by Gson is interesting and confusing to me... Can Multiline automatically map JSON strings to a nested Map? Is that why it uses Gson?
The class looks like:
package com.sungardas.cc.vsphere.docs;
import com.google.gson.annotations.Expose;
import com.sungardas.cc.documents.AbstractDocument;
import java.util.HashMap;
import java.util.Map;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.adrianwalker.multilinestring.Multiline;
/**
*
* @author <a href="https://github.com/InfoSec812">Deven Phillips</a>
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class VCenterConfig extends AbstractDocument {
// Defines a multi-line String literal in a more readable fashion
/**
{
"VirtualMachine": [
"name", "summary.config.uuid", "summary.config.memorySizeMB", "summary.config.numCpu",
"runtime.powerState", "runtime.host", "summary.config.template", "guestHeartbeatStatus",
"guest.disk", "guest.net", "guest.hostName", "guest.guestFamily", "guest.guestFullName",
"guest.guestId", "config.hardware.device", "config.hardware.numCoresPerSocket"
],
"ClusterComputeResource": [
"name", "summary.numHosts", "summary.totalMemory", "summary.numCpuCores", "host"
],
"Datastore": [
"name", "summary.freeSpace", "summary.capacity", "summary.uncommitted",
"summary.accessible", "summary.type", "host"
],
"HostSystem": [
"name", "vm"
],
"DistributedVirtualSwitch": [
"capability", "config", "networkResourcePool", "portgroup", "summary", "uuid"
],
"DistributedVirtualPortgroup": [
"config", "key", "portKeys"
],
}
*/
@Multiline
static String DEFAULT_PROPERTIES;
@Expose
private String host;
@Expose
private Integer port = 9443;
@Expose
private String username;
@Expose
private String password;
@Expose
private String site;
@Expose
private String location;
@Expose
private Map<String, String[]> properties = AbstractDocument.getGson().fromJson(DEFAULT_PROPERTIES, HashMap.class);
@Expose
private Integer maxObjects = 1000;
@Override
public String documentType() {
return "vcenter-config";
}
}
@InfoSec812 Multiline do nothing special to JSON. As I guess, charactors for new line or spaces affects validation of the JSON string.
I recommend to test as following
- Print the json string on the console
System.out.println(DEFAULT_PROPERTIES)
- Copy the result of 1 to a file ( ex) test.json )
- Read the content of 2, and try to parse it
This is definitely user error. The actual problem is the trailing comma after the "DistributedVirtualPortgroup" key's value, which JSON doesn't allow. (The JSON would work fine as a Javascript literal, however, because Javascript has looser parsing rules.)