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

Test class - Would someone be so kind??

Hi Everyone,
I'm very new to Apex code and am following the sample app that was introduced at the Salesforce Tour de Force show and attempting to learn the language.  I've created the following Apex class, but now need to unit test it and I just can't figure-out how to do it.  The workbook doesn't provide any instructions on how to write it and I've tried without success to get something running.

I talked to someone who knows Apex code and they indicated it would only take 7 or 8 lines of code to sufficiently test the attached code that would enable me to deploy it to my sandbox, but I really need some help here.
I know this is asking a lot, but could someone provide me what I need to test this code - with some remarks as well?  I would REALLY appreciate it!!
Here's the code:
public class MileageUtil {
 static final integer MAX_MILES_PER_DAY = 500;
 public static void areMilesAllowed(Mileage__c[] miles)  {
  Double totalMiles = 0;
  String createdbyId = UserInfo.getUserId();
 /* adds miles that were created in previous requests for today */
 for (Mileage__c mq: [select miles__c from Mileage__c
  where Date__c = TODAY and
  createdById = :createdbyId and
  miles__c != null]) {
  totalMiles += mq.miles__c;
 /* Totals the miles in the request */
 for (Mileage__c m:miles)  {
  totalMiles += m.miles__c;
  if (totalMiles > MAX_MILES_PER_DAY)
    m.addError ('Mileage request exceeds daily limit: ' + MAX_MILES_PER_DAY);

You're always going to have a difficult time unit testing your code due to the dynamic contents in your Mileage object.  Normally, you'd just add a testMethod to the class in the following manner:

public static testMethod void testAreMilesAllowed() 
  // create array of Mileage objects

// call areMilesAllowed function

// verify results

The standard pattern to follow in a testMethod is to set up the environment, call your code, then use System.assertEquals() to test the results, making sure that you pass in arguments (or call the test enough times) that the test method will cause each line of code to execute.

However, you're going to find a severe issue will crop up when you go to publish this class: the method you wrote is totally non-deterministic, and will return different results depending on when and where you call it.  As a result, since asserts failing will halt any further execution of your test code, you'll find quickly that while your code may be 100% or sufficiently covered in dev., in production it will be much lower, or fail to publish completely.

But don't fret -- you can make sure that your method is deterministic: DML statements in test methods are rolled back after the test executes.  For your test, you can set up by deleting all records out the Mileage table, insert some hard-coded values, then call your method to test and verify the results.  This way, you can be 100% sure the test will always run the same way no matter when you run it.  (Note: I'm 100% sure that inserts and updates are rolled back in test methods; I'm 99% sure that deletes would be, but I've never tried it personally.  Apex supports transactions with Database.setSavePoint() and Database.rollback(savepoint) methods -- you may need to use these explicitly in your unit test)

You'd run into this problem in no matter what language you'd use to unit test, any time you try to test a non-deterministic function.
Well, that's why I read these boards.  Looks like you can also use Test.setFixedSearchResults (new in 12.0), in conjunction with SOSL, to ensure that you're only getting back expected records from a continuously updated object.  This way you don't have to delete anything from your object in the test, just add some new records in, then use setFixedSearchResults to mark those as the only records which should be returned.