Testing Versioned Behavior in Apex Code

When you change the behavior in an Apex class or trigger for different package versions, it’s important to test that your code runs as expected in the different package versions. You can write test methods that change the package version context to a different package version by using the System.runAs method. You can only use System.runAs in a test method.

This sample shows a trigger with different behavior for different package versions. For more information about defining different behavior for package versions, see Version Apex Behavior.

1trigger oppValidation on Opportunity (before insert, before update) {
2
3    for (Opportunity opp : Trigger.new){
4    
5        // Add a new validation to the package
6        // Applies to versions of the managed package greater than 1.0
7        if (System.requestVersion().compareTo(new Version(1,0)) > 0) {
8            if (opp.Probability >= 50 && opp.Description == null) {
9                opp.addError('All deals over 50% require a description');
10            }
11        }
12
13        // Validation applies to all versions of the managed package.
14        if (opp.IsWon == true && opp.LeadSource == null) {
15            opp.addError('A lead source must be provided for all Closed Won deals');
16        }
17    }
18}

The following test class uses the runAs method to verify the trigger’s behavior with and without a specific version:

1@IsTest
2private class OppTriggerTests{
3
4   static testMethod void testOppValidation(){
5   
6      // Set up 50% opportunity with no description
7      Opportunity opp = new Opportunity();
8      opp.Name = 'Test Job';
9      opp.Probability = 50;
10      opp.StageName = 'Prospect';
11      opp.CloseDate = System.today();
12      
13      // Test running as latest package version
14      try{
15          insert opp;
16      }
17      catch(DMLException e){
18          Assert.isTrue(
19              e.getMessage().contains(
20                'All deals over 50% require a description'),
21                  e.getMessage());
22      }
23      
24      // Run test as managed package version 1.0
25      System.runAs(new Version(1,0)){
26          try{
27              insert opp;
28          }
29          catch(DMLException e){
30              Assert.isFalse(false, e.getMessage());
31          }
32      }
33
34      // Set up a closed won opportunity with no lead source
35      opp = new Opportunity();
36      opp.Name = 'Test Job';
37      opp.Probability = 50;
38      opp.StageName = 'Prospect';
39      opp.CloseDate = System.today();
40      opp.StageName = 'Closed Won';
41      
42      // Test running as latest package version
43      try{
44          insert opp;
45      }
46      catch(DMLException e){
47          Assert.isTrue(
48            e.getMessage().contains(
49              'A lead source must be provided for all Closed Won deals'),
50                e.getMessage());
51      }
52
53      // Run test as managed package version 1.0
54      System.runAs(new Version(1,0)){
55          try{
56              insert opp;
57          }
58          catch(DMLException e){
59              Assert.isTrue(
60                  e.getMessage().contains(
61                    'A lead source must be provided for all Closed Won deals'),
62                        e.getMessage());
63          }
64      }
65   }
66}