-
Notifications
You must be signed in to change notification settings - Fork 145
Unit test to verify multi-level additional data setter #114
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…ded a comment to explain the IllegalArgumentException
| } | ||
| } catch (IllegalArgumentException | IllegalAccessException e) { | ||
| logger.logError("Unable to access child fields of " + serializedObject.getClass().getSimpleName(), e); | ||
| //Not throwing the IllegalArgumentException as the Serialized Object would still be usable even if the additional data is not set. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not enough of an argument for me. Describe the situation where this error would happen (and unit test it) and and justify why you would not throw.
You need more unit test coverage of this method. Use a coverage tool till you have 100% coverage of every line and branch. What IDE are you using (Emma is good for Eclipse)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would argue that just because the Java reflection engine hands us a field that it won't let us access, isn't a good enough reason to throw an exception at the user. Especially when the only reason we are reflecting over it is because we are hunting for extra properties that might be there so that we can fill the additionalProperties collection.
I do agree that the try/catch is a bit too wide of a net and we should try and limit the lines we are actually swallowing exceptions for.
However, this brings me to my main concern here. If I understand this code, we are reflecting over every single property of every object that is returned from the Graph. This seems like an expensive solution to a problem that by definition is an exception case. The .Net library has the luxury of doing this because the deserializer library builds the list of unknown properties while it is parsing the JSON.
I really don't like the idea of running this chunk of reflection code on the retrieval of every single object. That just sounds like asking for trouble.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would argue that just because the Java reflection engine hands us a field that it won't let us access, isn't a good enough reason to throw an exception at the user.
That may be the case, just want it documented and reasoned. All of the objects being serialized/deserialized are objects defined in the SDK though right? So we should know what the variation in access is across the model objects is and can test these cases.
I'm only brushing the surface with my review because I'm too busy to study this AdditionalData stuff properly but it does seem fair enough that if JSON from API has a field that is not represented in the object then it is ok to ignore that field.
However, if the Java object has a field that the JSON doesn't have then we will throw probably with a NullPointerException (NPE). That is ugly and should be fixed if only to throw a more meaningful exception but perhaps just to ignore (log). Needs consideration and needs unit testing!
msgraph-sdk-java/src/main/java/com/microsoft/graph/serializer/DefaultSerializer.java
Line 137 in b4ecc09
| childAdditionalDataManager.setAdditionalData(rawJson.get(field.getName()).getAsJsonObject()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@davidmoten ,I agree that 100% code coverage is the ideal test case result that we should strive for. And we will further try to enhance this test case to cover most of the branching in the code.
As for the exceptions caught at the end of setting up additional data, these exceptions are thrown by field.get(object) method of java.lang.reflect.Field class. So, we are just catching it and not throwing it to break the flow.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, you are catching IllegalArgumentException and IllegalAccessException. A NullPointerException will be thrown not caught. This is why unit tests are important (in fact thinking about all scenarios is important because full line and branch test coverage would not find this necessarily).
|
I notice also that the setChildAdditionalData is recursive. This sets us up for an infinite recursion if object A has a reference to B and B has a reference to A as a simple example. Do we need protection for this and if not why not? |
|
I'm also concerned by
Again, forgive the superficial review! |
|
@davidmoten , as for your concern about infinite recursion. As we are recursively traversing the JSON object returned from Graph server, there is no chance of one JSON object being referred from a sub-element. Hence there will not be any infinite recursion scenario. |
Ok, thanks.
Ok, so I want to check this scenario. If
Will the additional data for deserialized B end up with x = y instead of x = z? Another scenario is
Will the additional data for deserialized B end up with x = y? If these are valid scenarios I'd like the desired outcomes to be unit tested. |
|
Until the scenarios I mention above have been addressed I think the original PR should be backed out of dev branch (and master if there). |
|
@davidmoten thanks for bringing this up, we will get working on fixing this issue. |
This comment has been minimized.
This comment has been minimized.
|
Conflicts have been resolved. A maintainer will take a look shortly. |
|
Hey @davidmoten |
src/main/java/com/microsoft/graph/serializer/DefaultSerializer.java
Outdated
Show resolved
Hide resolved
| final JsonElement elementRawJson = rawJsonArray.get(i); | ||
| setChildAdditionalData((IJsonBackedObject) element, elementRawJson.getAsJsonObject()); | ||
| // If the object is a list of Graph objects, iterate through elements | ||
| else if (fieldObject instanceof List) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a test for fieldObject instanceof HashMap using serializer.deserializeObject(sourcestring, class);
One test for a homogenous list of objects, and one for a hetergenous list of objects.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added a unit test. We currently don't have a case where hashmaps have heterogeneous values and I didn't want to add too much fake code in the test setup.
| childAdditionalDataManager.setAdditionalData(rawJson.get(field.getName()).getAsJsonObject().get(pair.getKey()).getAsJsonObject()); | ||
| setChildAdditionalData((IJsonBackedObject) child,rawJson.get(field.getName()).getAsJsonObject().get(pair.getKey()).getAsJsonObject()); | ||
| // If the item is a valid Graph object, set its additional data | ||
| if (child instanceof IJsonBackedObject) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to see a test in case where the child is a OData primitive, do we add non-schematized primitive fields to additionalData?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tweaked the last unit test I added so it tests for that as well.
Added a unit test case to verify multi-level additional data setter and added a comment to explain the IllegalArgumentException
Fixes #113
Changes proposed in this pull request
-Have Added a test function in AddtionalDataTests.java class.
-Have also added a comment in DefaultSerializer which explains the reason for not throwing IllegalArgumentException