To facilitate the development of robust, error-free code, Apex supports the creation and execution of unit tests. Unit tests are class methods that verify whether a particular piece of code is working properly. Unit test methods take no arguments, commit no data to the database, send no emails, and are flagged with the testMethod keyword or the isTest annotation in the method definition. Also, test methods must be defined in test classes, that is, classes annotated with isTest.
@isTest private class myClass { static testMethod void myTest() { // code_block } }
This is the same test class as in the previous example but it defines the test method with the isTest annotation instead.
@isTest private class myClass { @isTest static void myTest() { // code_block } }
This is an example of a test class that contains two test methods.
@isTest private class MyTestClass { // Methods for testing @isTest static void test1() { // Implement test code } @isTest static void test2() { // Implement test code } }
Classes and methods defined as isTest can be either private or public. The access level of test classes methods doesn’t matter. This means you don’t need to add an access modifier when defining a test class or test methods. The default access level in Apex is private. The testing framework can always find the test methods and execute them, regardless of their access level.
Classes defined as isTest must be top-level classes and can't be interfaces or enums.
Methods of a test class can only be called from a running test, that is, a test method or code invoked by a test method, and can't be called by a non-test request.
This example shows a class and its corresponding test class. This is the class to be tested. It contains two methods and a constructor.
public class TVRemoteControl { // Volume to be modified Integer volume; // Constant for maximum volume value static final Integer MAX_VOLUME = 50; // Constructor public TVRemoteControl(Integer v) { // Set initial value for volume volume = v; } public Integer increaseVolume(Integer amount) { volume += amount; if (volume > MAX_VOLUME) { volume = MAX_VOLUME; } return volume; } public Integer decreaseVolume(Integer amount) { volume -= amount; if (volume < 0) { volume = 0; } return volume; } public static String getMenuOptions() { return 'AUDIO SETTINGS - VIDEO SETTINGS'; } }
This is the corresponding test class. It contains four test methods. Each method in the previous class is called. Although this would have been enough for test coverage, the test methods in the test class perform additional testing to verify boundary conditions.
@isTest class TVRemoteControlTest { @isTest static void testVolumeIncrease() { TVRemoteControl rc = new TVRemoteControl(10); Integer newVolume = rc.increaseVolume(15); System.assertEquals(25, newVolume); } @isTest static void testVolumeDecrease() { TVRemoteControl rc = new TVRemoteControl(20); Integer newVolume = rc.decreaseVolume(15); System.assertEquals(5, newVolume); } @isTest static void testVolumeIncreaseOverMax() { TVRemoteControl rc = new TVRemoteControl(10); Integer newVolume = rc.increaseVolume(100); System.assertEquals(50, newVolume); } @isTest static void testVolumeDecreaseUnderMin() { TVRemoteControl rc = new TVRemoteControl(10); Integer newVolume = rc.decreaseVolume(100); System.assertEquals(0, newVolume); } @isTest static void testGetMenuOptions() { // Static method call. No need to create a class instance. String menu = TVRemoteControl.getMenuOptions(); System.assertNotEquals(null, menu); System.assertNotEquals('', menu); } }
Here are some things to note about unit tests.