Our tests are scheduled to be run in production on a daily basis. They usually starts let's say one hour before midnight and finishes one hour after midnight. And from time to time we are experiencing random test failures of random test methods, i.e. every time it's another test method, different class, part of business logic etc. (or if we are lucky everything executes successfully).
The only pattern we were able to identify is that failure always relates to invalid value of some date fields or formulas which relies on date calculation.
Our best guess: test method starts executing one day (one second before midnight and some test data are created using System.today() for some fields, business logic runs) and then results assertion happens next day (i.e. System.today() points to another date already).
We've tried to fix this by catching today's date at the beginning of the test method execution and kinda freeze it using wrappers/mocks/proxy whatever we could call it. As result failures almost disappeared (just 1-2 per week). The problem is that we have a lot of formulas in the system which uses TODAY() value and we can not mock it with our custom solution (same way as we did inside apex test code).
Is there anyway to mock date and time at the system/global level? Or maybe there is better idea how to handle this date/time bombs?
Rescheduling tests execution is not an option, cause according to our clients they have no control over it, i.e. no options to specify execution time in their test execution solution(
Bellow is the example of test method which could trigger such midnight problem (no even business logic here):
// executes before midnight: today = Aug 1 Account originalAccount = new Account( External_Date__c = System.today() ) ; insert originalAccount; Test.startTest(); Test.stopTest(); // executes after midnight: : today = Aug 2 Account actualAccount = [ SELECT Id, External_Date__c, Internal_Formula_Date__c FROM Account WHERE Id = :originalAccount.Id ]; // fails because Aug 1 != Aug 2; but we can mock this in our code System.assert(System.today(), actualAccount.External_Date__c); // fails as well. Internal_Formula_Date__c is defined as TODAY(), so we can not mock this!!! System.assert(System.today(), actualAccount.Internal_Formula_Date__c);