Testing the Domain layer

Testing your Domain code can be accomplished in the standard Force.com manner. Typically, test classes are named by suffixing Test at the end of the Domain class name, for example, RacesTest. Test methods have the option to test the Domain class code functionality either directly or indirectly.

Indirect testing is accomplished using only the DML and SOQL logic against the applicable Custom Objects and asserting the data and field errors arising from these operations. Here, there is no reference to your Domain class at all in the test code.

However, this only tests the Apex Trigger Domain class methods. For test methods that represent custom domain behaviors, you must create an instance of the Domain class. This section will illustrate examples of both indirect and direct testing approaches.

Unit testing

Although developing tests around the Service layer and related callers (controllers, batch, and so on) will also invoke the Domain layer logic, it is important to test as many scenarios specifically against the Domain layer as possible, passing in different configurations of record data to test both success and failure code paths and making sure that your Domain layer logic is as robust as possible. Wikipedia describes the definition of a unit test as follows (http://en.wikipedia.org/wiki/Unit_testing):

In computer programming, unit testing is a method by which individual units of source code, sets of one or more computer program modules together with associated control data, usage procedures, and operating procedures are tested to determine if they are fit for use. Intuitively, one can view a unit as the smallest testable part of an application. In procedural programming, a unit could be an entire module, but it is more commonly an individual function or procedure. In object-oriented programming, a unit is often an entire interface, such as a class, but could be an individual method. Unit tests are short code fragments created by programmers or occasionally by white box testers during the development process.

Testing of the Domain layer falls into this definition. The following sections illustrate the traditional and still very much valid approach to testing your Domain class code through setting up test data using DML and executing the code. In a later chapter, we will review an Apex Mocking framework (similar to Mockito in Java), which provides a much leaner and more targeted means to test your Domain code.

Test methods using DML and SOQL

To test the Apex Trigger methods of the Domain class, the traditional use of DML and SOQL can be applied alongside the use of the Apex runtime DMLException methods to assert not only the error message but also other details. The following Apex test method illustrates how to do this:

@IsTest
private static void testAddContestantNoneScheduled() {
  // Test data
  Season__c season = 
    new Season__c(Name = '2014', Year__c = '2014'),
  insert season;
  Driver__c driver = 
    new Driver__c(Name = 'Lewis Hamilton', DriverId__c = '42'),
  insert driver;
  Race__c race = 
   new Race__c(Name = 'Spa', Status__c = 'In Progress', 
     Season__c = season.Id);
  insert race;

  Test.startTest();
  try {
    // Insert Contestant to In Progress race
    Contestant__c contestant = 
        new Contestant__c(Driver__c = driver.Id, Race__c = race.Id);
    insert contestant;
    System.assert(false, 'Expected exception'),
  }
  catch (DMLException e) {
    System.assertEquals(1, e.getNumDml());
    System.assertEquals(
      'Contestants can only be added to Scheduled Races.',
      e.getDmlMessage(0));
    System.assertEquals(
      StatusCode.FIELD_CUSTOM_VALIDATION_EXCEPTION, 
      e.getDmlType(0));
   }
   Test.stopTest();
 }

The preceding error is a record-level error; the DMLException class also allows you to assert field-level information for field-level errors. The following code shows such a test assertion; the data setup code is not shown:

Test.startTest();
Try {
  contestant.Driver__c = anotherDriver.Id;
  update contestant;
  System.assert(false, 'Expected exception'),
}
catch (DmlException e) {
  System.assertEquals(1, e.getNumDml());
  System.assertEquals(
    'You can only change drivers for scheduled races',
    e.getDmlMessage(0));
  System.assertEquals(Contestant__c.Driver__c,
    e.getDmlFields(0)[0]);
  System.assertEquals(
   StatusCode.FIELD_CUSTOM_VALIDATION_EXCEPTION, 
   e.getDmlType(0));
}
Test.stopTest();

Test methods using the Domain class methods

In order to test custom Domain class methods, an instance of the Domain class should be created in the test method, using test records created in memory or queried from the database having been inserted as shown in the previous tests.

The following example shows the Contestants.awardChampionShip method being tested. Note that the test creates a temporary Unit Of Work but does not commit the work. This is not strictly needed to assert the changes to the records, as the Records property can be used to access the changes and assert the correct value that has been assigned:

@IsTest
private static void testAddChampionshipPoints() {
  // Test data
  ChampionshipPoints__c championShipPoints = 
    new ChampionshipPoints__c(Name = '1', PointsAwarded__c = 25);
  insert championShipPoints;		
  Season__c season = 
    new Season__c(Name = '2014', Year__c = '2014'),
  insert season;
  Driver__c driver = 
    new Driver__c(Name = 'Lewis Hamilton', DriverId__c = '42'),
  insert driver;
  Race__c race = 
    new Race__c(Name = 'Spa', Status__c  = 'Scheduled', 
      Season__c = season.Id);
  insert race;
  Contestant__c contestant = 
    new Contestant__c(Driver__c = driver.Id, Race__c = race.Id);
  insert contestant;
  race.Status__c = 'Finished';
  update race;
  contestant.RacePosition__c = 1;
  update contestant;

  Test.startTest();
    Contestants contestants = 
      new Contestants(new List<Contestant__c> { contestant });
  contestants.awardChampionshipPoints(Application.UnitOfWork.newInstance());
  System.assertEquals(25, ((Contestant__c)contestants.Records[0]).ChampionshipPoints__c);
  Test.stopTest();
}

Tip

Performing SOQL and DML in tests is expensive in terms of CPU time and adds to the overall time it takes to execute all application tests, which becomes important once you start to consider Continuous Integration (covered in a later chapter). For example, whether it is always necessary to commit data updates from the Domain layer, as Service layer tests might also be performing these types of operations and asserting the results.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.116.62.168