I have a method called JsonMarshall(T t) that takes an object and converts it into Json String. Inside this method I'm using the Objectmapper to accomplish this task:
mapper.writerWithDefaultPrettyPrinter().writeValueAsString(t)
Now, lets say I have a class ClientName with the attributes Title and Name that I'm using for my test. Now when I try to convert ClientName into json string with my method and test this method by asserting its output against some expected Json String such as:
expectedString = "{\"title\":\"RandomTitle",\"Name\":\"RandomName\"}"
I get two scenarios:
Test fails when I use mapper.writerWithDefaultPrettyPrinter().writeValueAsString(t) in my method.
Test passes when I only do mapper.writeValueAsString(t)
So I guess the indentation of the writerWithDefaultPrettyPrinter() is causing the test to fail.
Any ideas how I can go about making this test pass for the first scenario?
I assume the first test fails because the output is pretty printed and contains additional format signs such as line breaks and whitespaces.
What you could do:
Just use another expected string in the first test method.
Parse the return string of your method under test and use the deserialized object for the test method.
You can use a JsonPath lib for your test (Works similar to XPath).
I use JsonPathResultMatcher to test RESTful Webservices based on the Spring Framework.
As an alternative to #Patrick's perfectly reasonable options, I'd suggest a fourth choice: You can mock the Objectmapper with a tool like JMockit, Mockito or Easymock, and simply ensure that your JsonMarshall method calls the appropriate method(s) on Objectmapper.
This, of course, assumes that you have no doubts that mapper.writerWithDefaultPrettyPrinter().writeValueAsString() does what it is supposed to do and that it is what you want to do. If you have any doubts about either of these conditions, it would be best not to mock, at least for now.
Related
I am building a Rest API using spring boot and Scala based on the below suggestion. I am successfully able to call the methods in Scala but the case class is not working the way it is designed.
When I try to create a Json using net.liftweb.json, I am getting additional string as "$outer":{}. I don't want this additional string in my output.
Note that the spring boot is expecting class instead of object. I suspect this could be an issue. Can you help me on this.
My case class looks like this:
case class BasicSrch(size: String, query: Match)
Erroneous output
{"$outer":{},"size":"10","query":{"$outer":{},"match":{"$outer":{},"_all":{"$outer":{},"query":"SNOW","operator":"and"}}}}
Expected Output
{"size":"10","query":{"match":{"_all":{"query":"VALLE","operator":"and"}}}}
If you are writing UTF-8 encoded JSON to the byte array or OutputStream then try jsoniter-scala: https://github.com/plokhotnyuk/jsoniter-scala
It will not serialize any other fields except those which are defined in a primary constructor of the case class.
In a test suite using chai 'should' asserts, the following returns false:
some.json.blob.should.equal(some.other.json.blob);
However, this returns true:
JSON.stringify(some.json.blob).should.equal(JSON.stringify(some.other.json.blob));
I know that the stringify() function is not the most robust way to test for JSON equivalence, so I want to find a way to compare the JSON directly without going through stringify. How can I compare the objects directly without using JSON.stringify()?
To compare JSON without using JSON.stringify, use a deep equal with your chai assertion:
some.json.blob.should.deep.equal(some.other.json.blob);
See Chai's documentation for more details on deep.equal.
I want to use the jmeter if controller and use a jmeter variable which I get while processing the previous response.
I have two services search and register. The logic I want to use is hit the search service, if I get a good response (i.e. the search exists) no need to register. If the search is empty hit register service and check the search service again.
So I have a Simple controller. Under simple controller I have search service with BSF assertion. Next thing under simple controller is the if controller (with register service) for which I need a variable (say ${found} )
I will be creating the variable in bsf assertion as
import groovy.json.*
def slurper = new JsonSlurper()
def result = slurper.parseText(prev.getResponseDataAsString())
if (result.id != null ) {
def found = 0 // can be text logical or any other type ..
}
Question: Can I use the variable ${found} created in the bsf assertion search service as a condition for If controller ? Will it be available beyond the service. Will it be better to have it as user defined variable ?
Depending on found variable type it can be:
vars.put("found", found); - for String
vars.put("found", String.valueOf(found)); - for chars, integers, floats, doubles, booleans, etc.
vars.putObject("found", found) - for anything which cannot be cast to a String
props.put(found, found); - for any Object types. Opposite to JMeter Variables JMeter Properties have "global" scope and Variables visibility is limited to the current thread group only so if you need to pass this value to another Thread Group you need to use properties.
Be careful while setting conditions in the If Controller as in case of string literals you'll need to put both variable and value in quotation marks like:
"${found}"=="someid"
See How to use JMeter's 'IF' Controller and get Pie. guide for more details.
By the way, there is a couple of test elements available via JMeter Plugins which are designed to work with JSON data so you won't have to use BSF scripting:
JSON Path Extractor - to perform correlation on JSON data
JSON Path Assertion - to use assertions on response
yes the variable "found" can be used. But you need to add the following at the end of your code
vars.put("found",found);
Hope this will help.
I want to test a method like this
public List<String> giveStrings();
Using hamcrest I can test for the returned type, for example
assertThat(giveStrings(), instanceOf(ArrayList.class));
But what I want to know is whether it's a List of Strings. Is there an existing matcher for that?
Thanks in advance
So simple answer is No because at runtime Java does type-erasure so all generics are converted to Object. So at runtime your List<String> is actually just a List or List<Object>. The String type information is lost.
Consider using
IsIterableContainingInOrder.containsInOrder(
CoreMatchers.instanceOf(String.class),
...)
Per comment, use Every
assertThat(myList, Every.everyItem(instanceOf(String.class));
I'm trying to parse a grails parameter map to a Json String, and then back to a parameter map. (For saving html form entries with constraint-violations)
Everything is fine as long as there is no hasMany relationship in the parameter-map.
I'm using
fc.parameter = params as JSON
to save the params as JSON String.
Later I'm trying to rebuild the parameter map and create a new Domain-Object with it:
new Foo(JSON.parse(fc.parameter))
Everything is fine using only 1:1 relationships (states).
[states:2, listSize:50, name:TestFilter]
But when I try to rebuild a params-map with multi-select values (states)
[states:[1,2], listSize:50, name:TestFilter]
I'm getting this IllegalStateException:
Failed to convert property value of type org.codehaus.groovy.grails.web.json.JSONArray to required type java.util.Set for property states; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [de.gotosec.approve.State] for property states[0]: no matching editors or conversion strategy found
I tried to use this, but without success:
JSON.use("deep") {
new Foo(JSON.parse(fc.parameter))
}
You can use JsonSlurper instead of the converters.JSON of grails, it maps JSON objects to Groovy Maps. I think this link also might help you.
Edit: Now, if the problem is binding the params map to your domain, you should try using bindData() method, like:
bindData(foo, params)
Note that this straightforward use is only if you're calling bindData inside a controller.
What seems to be happening in your case is that Grails is trying to bind a concrete type of List (ArrayList in the case of JsonSlurper and JSONArray in the case of converters.JSON) into a Set of properties (which is the default data structure for one-to-many associations). I would have to take a look at your code to confirm that. But, as you did substitute states: [1,2] for a method of your app, try another test to confirm this hypothesis. Change:
states:[1,2]
for
states:[1,2] as Set
If this is really the problem and not even bindData() works, take a look at this for a harder way to make it work using object marshalling and converters.JSON. I don't know if it's practical for you to use it in your project, but it sure works nicely ;)