17

So let's say I've got a class that looks like this:

public class APIParams {
        public String name; 
        public String category; 
        public Boolean taxable = false;
}

Then I have a custom REST webservice (apexrest) that takes JSON and deserializes it to an object of this class, like so:

    String rawParams = RestContext.request.requestBody.toString();
    APIParams p = (APIParams) JSON.deserialize(rawParams, APIParams.class);

The difference in behavior comes in how it handles it if I don't pass in that "taxable" property. Here's what I'm seeing:

  • In a unit test, if I pass in JSON that doesn't include "taxable", I end up with an object where taxable = false. (i.e. it respects the default value in the class definition)
  • OTOH, if I pass in the same JSON via the API, I end up with an object where taxable = null. No default is applied.

Is there some sort of rhyme & reason to this difference, or is this effectively a bug? As you might imagine, this makes it difficult to write tests that effectively cover the behavior that we will see in production.

Thanks!

  • 2
    Can you call the web service in the development environment? It might be more of a unit testing versus actual web service issue rather than a production vs development issue. You could also try calling JSON.deserialize in anonymous Apex in production. – Daniel Ballinger Nov 19 '14 at 23:31
  • 2
    Note that an apex rest service will do automatic deserialization if you make the custom type an argument to your post-annotated method. I tend to put getters on my Boolean properties in custom types that look like return taxable == null ? false : taxable; – cropredy Nov 19 '14 at 23:43
  • @DanielBallinger I do believe this is a matter of unit test vs API, rather than what kind of org it is. I will update the title of the post. It's still a problem, though. ;) – mscholtz Nov 19 '14 at 23:47
  • @crop1645 thanks for the tip on the automatic deserialization. I may try that at some point on the off chance that different syntax may lead to different behavior. And yes, I know there are lots of ways to work around this, but regardless of that, IMHO the test should work the same as the API call so that it's more likely I'll know that a workaround is needed. – mscholtz Nov 19 '14 at 23:51
  • Well, Boolean variables in custom types or standalone can definitely have null values; they can't in sobjects. You should post your unit test code (stripped to its essence) – cropredy Nov 19 '14 at 23:55
0

I tried a test as you mentioned but it has the same behavior on Test as well as on real usage.

@IsTest
public class APIParamsTest {
    @isTest static void test() {
        String rawParams = '{"name":"karthik"}';
        APIParams p = (APIParams) JSON.deserialize(rawParams, APIParams.class);
        System.assert(p.name == 'karthik');
        System.assert(p.taxable == false);
    }
}

Even in this test the assert on taxable field fails.

  • I am not sure how its different from the test you wrote, but I find the behavior consistent everywhere.

  • To get consistent behavior I think its better to handle it in getter than through default variables As @crop1645 mentioned.

    return taxable == null ? false : taxable;

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.