function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
AngiB.ax1285AngiB.ax1285 

Problem with OR (||)

I have an Apex class that is run either via a button on a page or as a scheduled task.

 

It is long and does many things - I am just having a TINY problem with it.

I fear that what I am writing below isn't going to make ANY sense to anyone - it is very hard to describe - but I will try my best....

 

My class has what I think is called a property called 'IsTest'.

When the class is called via the page button or scheduled task IsTest is set to FALSE.

When the class is called from inside it's test class IsTest is set to TRUE.

The purpose of IsTest is to allow the test class to ACTUALLY execute all the code in the class since it is very date sensitive.

 

 

A variable called 'Today' exists - in the example I am running I am choosing that to be a specific date (Feb 29 2012).

 

The code is looping around through the records in a custom object - some of them are Monthly and some Annually....

 

 

if(obj.AcctSol__Depreciation_Schedule__r.AcctSol__Depreciation_cycle__c !='' && obj.AcctSol__Depreciation_Schedule__r.AcctSol__Depreciation_cycle__c == 'Monthly')

                        {

                            try{

                            

                            Date endDate = today.addMonths(1);

                            endDate = endDate.toStartOfMonth();

                            endDate = endDate.addDays(-1);

                            if(endDate == today || isTest == true)

                            {

                           // a bunch of stuff happens 

                        }

                    }

                }

else if(obj.AcctSol__Depreciation_Schedule__r.AcctSol__Depreciation_cycle__c !='' && obj.AcctSol__Depreciation_Schedule__r.AcctSol__Depreciation_cycle__c == 'Annually')

                   {

                        try

                        {

                           

                            integer Curr_Year = today.year();

                            Date endDate_yr;

                            if(objconfg!=null && objconfg.Fiscal_year_start__c!=null)

                            {

  endDate_yr = Date.valueOf(Curr_Year+'-    '+objconfg.Fiscal_year_start__c+'-01');

                            endDate_yr = endDate_yr.addDays(-1);

                           

                           

                            }

                            if(today == endDate_yr || isTest == true)

                        {

                                                                  

                           // a bunch of stuff happens 

                        }

                    }

                 }

 

The problem is that when IsTest is FALSE and I set my date to be the proper one (Feb 29 2012) based on our data...

 

The first If statement duplicated below evalutes to TRUE and the code within that IF executes...

                            if(endDate == today || isTest == true)

 

BUT The second If statement duplicated below evalutes to FALSE and the code within that IF DOES NOT execute...

                            if(today == endDate_yr || isTest == true)

  

To confirm that the problem isn't with the date related to the data If I change that second IF to be:

                            if(today == endDate_yr)

 

Then the second If statement evaluates properly to TRUE and the code within that IF executes.

 

Based on that little experiment I am confident that the first component of the OR is evaluating to be TRUE.

 

So why is the code inside my second if not ever executing unless isTest is TRUE?

 

For the moment I have to leave the second if as if(today == endDate_yr) so that in a production situation the code actually works.

But this has dropped my code coverage from 83 down to 52 on this class so I would like to figure this out.

 

Not to mention clearly OR (||) is working differently than I think it does - it would be good to understand.

 

Thanks in advance for any assistance you can provide me (THE DEFINITION of an Apex Newbie)

 

Best Answer chosen by Admin (Salesforce Developers) 
sfdcfoxsfdcfox

Short-circuit or ( || ) and short-circuit and ( && ) work as they do in other languages that support this type of operation. They work on the following principle: if the left operand makes the result obvious, then the right side is not evaluated. This means that if the left side of a || is true, the right-hand side is not evaluated. Similarly, if the left-hand side of a && is false, the right side is not evaluated. Contrast this to | and &, which evaluate the right side regardless. Consider the following:

 

String s = null;
if(s == null | s.length() == 0) { // ERROR: System.NullPointerException

}

To fix this, we want to not call String.length() if s is null. We do this using the || operator:

 

String s = null;
if(s == null || s.length() == 0) { // OKAY!

}

You can also do this to make a test pass, such as:

 

if(Test.isRunningTest() || sendHttpRequest()) { // We can't send Http requests during tests

}

So, if your code is failing, it's because the first condition failed AND isTest was not true for some reason. You should use Test.isRunningTest() instead of depending on a boolean field in your class.

 

Try using some debug statements and make sure that endDate_yr is actually being set correctly in all cases.

All Answers

sfdcfoxsfdcfox

Short-circuit or ( || ) and short-circuit and ( && ) work as they do in other languages that support this type of operation. They work on the following principle: if the left operand makes the result obvious, then the right side is not evaluated. This means that if the left side of a || is true, the right-hand side is not evaluated. Similarly, if the left-hand side of a && is false, the right side is not evaluated. Contrast this to | and &, which evaluate the right side regardless. Consider the following:

 

String s = null;
if(s == null | s.length() == 0) { // ERROR: System.NullPointerException

}

To fix this, we want to not call String.length() if s is null. We do this using the || operator:

 

String s = null;
if(s == null || s.length() == 0) { // OKAY!

}

You can also do this to make a test pass, such as:

 

if(Test.isRunningTest() || sendHttpRequest()) { // We can't send Http requests during tests

}

So, if your code is failing, it's because the first condition failed AND isTest was not true for some reason. You should use Test.isRunningTest() instead of depending on a boolean field in your class.

 

Try using some debug statements and make sure that endDate_yr is actually being set correctly in all cases.

This was selected as the best answer
AngiB.ax1285AngiB.ax1285

Brilliant!!!

 

I changed BOTH if statements from:

 

if(endDate == today || isTest == true)

and

if(today == endDate_yr || isTest == true)

 

To

 

if(endDate == today || Test.isRunningTest() )

and

if(today == endDate_yr || Test.isRunningTest())

 

I ran both the test class and the scenarios that I think should have caused problems and there are no problems!

My data gets into both IF's when it should.

 

Now I expect you are correct in that my problem wasn't actually IsTest but rather endDate_yr... but I will have to hand

the code over to my collegue who is the better tester and make sure he cannot break anything with varying data sets.

 

THANK YOU VERY MUCH for explaining that || does in fact work the way that I thought it would/should.

Also more thanks for the Test.isRunningTest() syntax which makes things much easier rather than setting booleans

all over the code (FYI - it isn't my code - someone else wrote it - I was just confronted with a bug)

 

:-D This is good - I can go to sleep tonight without this little problem running through my head